在iOS中获取设备位置(仅限国家/地区)

我需要获取iOS设备的国家位置。

我一直在尝试与MKReverseGeocoder使用CoreLocation。 但是,这似乎相当频繁地返回erralous。 而我只需要国家,不需要街道等。

这怎么能以更稳定的方式来完成呢?

NSLocale只是一个关于当前使用的区域设置的设置,并不意味着你所在的实际国家。

使用CLLocationManager获取当前位置和CLGeocoder执行反向地理编码。 你可以从那里得到国家的名字。

 NSString *countryCode = [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode]; 

会给你一个像“美国”(美国),“ES”(西class牙)等标识符


Swift 3

 let countryCode = NSLocale.current.regionCode 

Swift 2.2中

 let countryCode = NSLocale.currentLocale().objectForKey(NSLocaleCountryCode) as String 

与基于CLLocationManager的解决scheme相比,这种方法有优点和缺点。 主要的一点是,如果用户对其进行不同的configuration,则不能保证这是设备在物理上的位置。 这也可以看作是一个专业人士,因为它反映了一个用户在精神上/文化上与哪个国家相匹配 – 所以如果我出国度假,那么这个地区仍然是我的祖国。 然而,一个非常大的职业是这个API不需要像CLLocationManager那样的用户权限。 所以如果你还没有获得使用用户位置的权限,并且你不能真正certificate在用户面前抛出一个popup对话框(或者他们已经拒绝了这个popup窗口,并且你需要一个回退),那么这可能是你的API想用。 一些典型的用例可能是个性化的(例如文化相关内容,默认格式等)和分析。

@丹尼斯的答案是好的 – 这里有一些代码将他的答案付诸实践。 这是针对您已设置为符合CLLocationManagerDelegate协议的自定义类。 这有点简单(例如,如果位置pipe理器返回多个位置,它只是与第一个位置一起),但应该给人们一个体面的开始…

 - (id) init //designated initializer { if (self) { self.locationManager = [[CLLocationManager alloc] init]; self.geocoder = [[CLGeocoder alloc] init]; self.locationManager.delegate = self; [self.locationManager startMonitoringSignificantLocationChanges]; } return self; } - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { if (locations == nil) return; self.currentLocation = [locations objectAtIndex:0]; [self.geocoder reverseGeocodeLocation:self.currentLocation completionHandler:^(NSArray *placemarks, NSError *error) { if (placemarks == nil) return; self.currentLocPlacemark = [placemarks objectAtIndex:0]; NSLog(@"Current country: %@", [self.currentLocPlacemark country]); NSLog(@"Current country code: %@", [self.currentLocPlacemark ISOcountryCode]); }]; } 

这是另一种可能过分迂回的方法。 其他解决scheme基于手动设置(NSLocale)或请求使用可以被拒绝的位置服务(CLLocationManager)的权限,因此它们有缺陷。

您可以根据当地时区获取当前的国家/地区。 我的应用程序与安装pytz的运行python的服务器进行交互,并且该模块为时区string提供国家代码字典。 我只需要让服务器知道国家,所以我不必完全在iOS上进行设置。 在Python方面:

 >>> import pytz >>> for country, timezones in pytz.country_timezones.items(): ... print country, timezones ... BD ['Asia/Dhaka'] BE ['Europe/Brussels'] BF ['Africa/Ouagadougou'] BG ['Europe/Sofia'] BA ['Europe/Sarajevo'] BB ['America/Barbados'] WF ['Pacific/Wallis'] ... 

在iOS端:

 NSTimeZone *tz = [NSTimeZone localTimeZone]; DLog(@"Local timezone: %@", tz.name); // prints "America/Los_Angeles" 

我有我的服务器发送本地时区名称,并在pytz country_timezones字典中查找它。

如果您使用pytz或其他来源的iOS版本的字典,您可以使用它来立即查找国家代码,而无需服务器的帮助,基于时区设置,这通常是最新的。

虽然我可能会误解NSLocale。 它是否通过区域格式设置或时区设置为您提供国家/地区代码? 如果是后者,那么这只是获得相同结果的更复杂的方式。

这是@丹尼斯和@马特的答案放在一起的Swift 3解决scheme:

导入UIKit导入CoreLocation

 class ViewController: UIViewController, CLLocationManagerDelegate { let locationManager = CLLocationManager() let geoCoder = CLGeocoder() override func viewDidLoad() { super.viewDidLoad() locationManager.requestAlwaysAuthorization() if CLLocationManager.locationServicesEnabled() { locationManager.delegate = self locationManager.startMonitoringSignificantLocationChanges() } } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let currentLocation = locations.first else { return } geoCoder.reverseGeocodeLocation(currentLocation) { (placemarks, error) in guard let currentLocPlacemark = placemarks?.first else { return } print(currentLocPlacemark.country ?? "No country found") print(currentLocPlacemark.isoCountryCode ?? "No country code found") } } } 

不要忘记在Info.plist设置NSLocationAlwaysUsageDescription

 NSLocale *countryLocale = [NSLocale currentLocale]; NSString *countryCode = [countryLocale objectForKey:NSLocaleCountryCode]; NSString *country = [countryLocale displayNameForKey:NSLocaleCountryCode value:countryCode]; NSLog(@"Country Locale:%@ Code:%@ Name:%@", countryLocale, countryCode, country); //Country Locale:<__NSCFLocale: 0x7fd4b343ed40> Code:US Name:United States 

Swift 3更简单:

 let countryCode = Locale.current.regionCode 

您可以从CLLocation获取NSTimeZone: https : //github.com/Alterplay/APTimeZones并在本地工作。

如果你只对电话设备感兴趣,那么这里提到的技术可能对你有用: 确定iPhone用户的国家

这是Swift 3中的一个快速循环,它返回一个完整的国家代码列表。

 let countryCode = NSLocale.isoCountryCodes for country in countryCode { print(country) }