我发现了一种使用 CLGeocoder 的有趣方法,我将其放入 CLLocation 上的一个类别中。有趣的部分如下所示:
-(void)timeZoneWithBlock:(void (^)(NSTimeZone *timezone))block {
[[[CLGeocoder alloc] init] reverseGeocodeLocation:self completionHandler:^(NSArray *placemarks, NSError *error) {
NSTimeZone *timezone = nil;
if (error == nil && [placemarks count] > 0) {
CLPlacemark *placeMark = [placemarks firstObject];
NSString *desc = [placeMark description];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"identifier = \"([a-z]*\\/[a-z]*_*[a-z]*)\"" options:NSRegularExpressionCaseInsensitive error:nil];
NSTextCheckingResult *result = [regex firstMatchInString:desc options:0 range:NSMakeRange(0, [desc length])];
NSString *timezoneString = [desc substringWithRange:[result rangeAtIndex:1]];
timezone = [NSTimeZone timeZoneWithName:timezoneString];
}
block(timezone);
}];
}
用法是这样的:
CLLocation *myLocation = ...
[myLocation timeZoneWithBlock:^(NSTimeZone *timezone) {
if (timezone != nil) {
// do something with timezone
} else {
// error determining timezone
}
}];
尽管需要网络连接和异步工作,但我发现这是获取某个位置的时区的最可靠方法。
多年后编辑
自从在 iOS9 中将 timeZone 属性添加到 CLPlacemark 以来,这个答案并没有很好地老化(感谢 Ortwin Genz)。这是一个更新的类别方法:
-(void)timeZoneWithBlock:(void (^)(NSTimeZone *timezone))block {
[[[CLGeocoder alloc] init] reverseGeocodeLocation:self completionHandler:^(NSArray *placemarks, NSError *error) {
NSTimeZone *timeZone = nil;
if (error == nil && [placemarks count] > 0) {
CLPlacemark *placeMark = [placemarks firstObject];
timeZone = placeMark.timeZone;
}
block(timeZone);
}];
}