Получить расположение устройства (только страна) в iOS
Мне нужно получить расположение страны устройства iOS.
Я пытался использовать CoreLocation с MKReverseGeocoder. Однако это, кажется, возвращается ошибочным довольно часто. А мне нужна только страна, не нужны улицы и все такое.
Как это можно сделать более стабильным способом?
12 ответов:
NSLocaleЭто просто настройка о текущих региональных настройках, это не означает, что фактическая страна, в которой вы находитесь.использовать
CLLocationManagerполучить текущее местоположение &CLGeocoderдля выполнения обратного геокодирования. Вы можете получить название страны оттуда.
NSString *countryCode = [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode];вы получите идентификатор, например, " US "(США)," ES " (Испания) и т. д.
на Swift 3:
let countryCode = NSLocale.current.regionCodeна Swift 2.2:
let countryCode = NSLocale.currentLocale().objectForKey(NSLocaleCountryCode) as Stringпо сравнению с решением на основе CLLocationManager этот подход имеет свои плюсы и минусы. Основной недостаток заключается в том, что он не гарантирует, что это то, где устройство физически, если пользователь настраивает его по-другому. Это, однако, также можно рассматривать как профи, так как это вместо этого показывает, с какой страной пользователь мысленно / культурно связан - так что если, например, я еду за границу в отпуск, то локаль все еще установлена в мою родную страну. Однако довольно большой pro заключается в том, что этот API не требует разрешения пользователя, как это делает CLLocationManager. Поэтому, если вы еще не получили разрешение на использование местоположения пользователя, и вы не можете действительно оправдать бросание всплывающего диалога в лицо пользователя (или они уже отклонили это всплывающее окно, и вам нужен запасной вариант), то это, вероятно, API вы хотите использовать. Некоторые типичные случаи использования для этого могут быть персонализацией (например, культурно релевантный контент, форматы по умолчанию и т. д.) и аналитика.
@ответ Дениса хорош - вот некоторый код, применяющий его ответ на практике. Это для пользовательского класса, который вы установили в соответствии с
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]); }]; }
вот ответы @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") } } }не забудьте установить
NSLocationAlwaysUsageDescriptionилиNSLocationWhenInUseUsageDescriptionнаInfo.plistкак хорошо!
вот альтернативный, возможно, чрезмерно окольный метод. Другие решения основаны на ручных настройках (NSLocale) или на запросе разрешения на использование служб определения местоположения, которые могут быть отклонены (CLLocationManager), поэтому они имеют недостатки.
вы можете получить текущую страну на основе местного часового пояса. Мое приложение взаимодействует с сервером под управлением Python с установленным pytz, и этот модуль предоставляет словарь кодов стран для строк часового пояса. Мне только очень нужно пусть сервер знает страну, поэтому мне не нужно полностью настраивать его на iOS. На стороне питона:
>>> 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.
Если вы сделаете iOS-версию словаря доступной в pytz или каком-либо другом источнике, вы можете использовать его для немедленного поиска кода страны без помощи сервера на основе настроек часового пояса, которые часто бывают в курсе событий.
возможно, я неправильно понимаю NSLocale. Дает ли он вам код страны через региональные настройки форматирования или настройки часового пояса? Если последнее, то это просто более сложный способ получения того же результата...
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
вы можете получить NSTimeZone от CLLocation:https://github.com/Alterplay/APTimeZones и работает локально.
Если вы интересуетесь только телефонными устройствами, то техника, упомянутая здесь, может быть вам полезна: определить страну пользователя iPhone
вот быстрый цикл в Swift 3, который возвращает полный список кодов стран.
let countryCode = NSLocale.isoCountryCodes for country in countryCode { print(country) }
@Rob
let locale = Locale.current let code = (locale as NSLocale).object(forKey: NSLocale.Key.countryCode) as! String?используя этот код, вы получите свой код страны региона, и если вы не получили еще, то измените его, просто зайдите в настройки телефона- > общие->язык и регион и установите свой регион, который вы хотите
Swift 4.0 код для получения названия страны в соответствии с набором регионов:
let countryLocale = NSLocale.current let countryCode = countryLocale.regionCode let country = (countryLocale as NSLocale).displayName(forKey: NSLocale.Key.countryCode, value: countryCode) print(countryCode, country)печать: необязательно ("NG") необязательно ("Нигерия"). //для региона Нигерия set
Comments