joh*_*han 59 core-location ios
我需要获取iOS设备的国家/地区位置.
我一直在尝试将CoreLocation与MKReverseGeocoder一起使用.然而,这似乎经常发生错误.我只需要这个国家,不需要街道等.
如何以更稳定的方式完成?
Mar*_*aek 95
NSString *countryCode = [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode];
Run Code Online (Sandbox Code Playgroud)
会给你一个标识符,例如"US"(美国),"ES"(西班牙)等.
在Swift 3中:
let countryCode = NSLocale.current.regionCode
Run Code Online (Sandbox Code Playgroud)
在Swift 2.2中:
let countryCode = NSLocale.currentLocale().objectForKey(NSLocaleCountryCode) as String
Run Code Online (Sandbox Code Playgroud)
与基于CLLocationManager的解决方案相比,这种方法有利有弊.主要的缺点是,如果用户以不同方式配置设备,则无法保证这是设备的物理位置.然而,这可以被视为专业人士,因为它反而显示用户在精神上/文化上与哪个国家保持一致 - 因此,如果我出国度假,那么该地区仍然设置在我的祖国.然而,一个非常大的专业人士是这个API不需要像CLLocationManager那样的用户权限.因此,如果你还没有获得使用用户位置的权限,并且你无法证明在用户面前抛出弹出对话框(或者他们已经拒绝了弹出窗口而你需要回退),那么这可能是你的API想用.一些典型的用例可能是个性化(例如文化相关内容,默认格式等)和分析.
Den*_*nis 41
NSLocale 只是关于当前使用的区域设置的设置,它并不意味着您所在的实际国家/地区.
使用CLLocationManager来获取当前位置及CLGeocoder执行反向地理编码.你可以从那里获得国家名称.
Mat*_*att 15
@Denis的答案很好 - 这里有一些代码将他的答案付诸实践.这适用于您已设置为符合CLLocationManagerDelegate协议的自定义类.它有点简化(例如,如果位置管理器返回多个位置,它只是与第一个位置一起),但应该给人们一个不错的开始......
- (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]);
}];
}
Run Code Online (Sandbox Code Playgroud)
小智 11
这是@Denis和@Matt的答案,为Swift 3解决方案拼凑而成:
import UIKit
import 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")
}
}
}
Run Code Online (Sandbox Code Playgroud)
别忘了设置NSLocationAlwaysUsageDescription或者NSLocationWhenInUseUsageDescription进入Info.plist!
小智 8
正如@Denis 所提到的,这Locale只是关于当前使用的区域设置的设置,并不意味着您所在的实际国家/地区。
但是,建议使用CLLocationManager来获取当前位置并CLGeocoder执行反向地理编码,这意味着提示用户访问位置服务。
如何从移动运营商获取国家代码?
import CoreTelephony
guard carrier = CTTelephonyNetworkInfo().subscriberCellularProvider else {
//iPad
return
}
let countryST = carrier.isoCountryCode!
Run Code Online (Sandbox Code Playgroud)
这是另一种可能过于迂回的方法.其他解决方案基于手动设置(NSLocale)或请求允许使用可拒绝的位置服务(CLLocationManager),因此它们有缺点.
您可以根据当地时区获取当前国家/地区.我的应用程序与安装了pytz的运行Python的服务器连接,该模块为时区字符串提供了国家代码字典.我只需要让服务器知道这个国家,所以我不必完全在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']
...
Run Code Online (Sandbox Code Playgroud)
在iOS方面:
NSTimeZone *tz = [NSTimeZone localTimeZone];
DLog(@"Local timezone: %@", tz.name); // prints "America/Los_Angeles"
Run Code Online (Sandbox Code Playgroud)
我让我的服务器以本地时区名称发送,并在pytz country_timezones字典中查找.
如果您在pytz或其他来源中提供字典的iOS版本,则可以使用它在没有服务器帮助的情况下立即查找国家/地区代码,具体取决于时区设置(通常是最新的).
我可能会误解NSLocale.它是否通过区域格式设置首选项或时区设置为您提供国家/地区代码?如果是后者,那么这只是获得相同结果的一种更复杂的方式......
如果由于某些原因不起作用,请使用该CoreTelephony方法作为后备方法。Locale.current.regionCode
import CoreTelephony\n\nif let carriers = CTTelephonyNetworkInfo().serviceSubscriberCellularProviders?.values, let countryCode = Array(carriers).compactMap { $0.isoCountryCode }.first {\n print("\xe2\x9d\xa4\xef\xb8\x8f \\(countryCode)")\n}\nRun Code Online (Sandbox Code Playgroud)\n
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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
56010 次 |
| 最近记录: |