Получить местоположение устройства (только страны) в iOS
Мне нужно получить расположение в стране устройства iOS.
Я пытаюсь использовать CoreLocation с MKReverseGeocoder. Однако это, как представляется, довольно часто возвращается. И мне нужна только страна, нет необходимости в улицах и т.д.
Как это можно сделать более стабильным образом?
Ответы
Ответ 1
NSLocale
- это всего лишь настройка существующих региональных настроек, это не значит, что вы находитесь в той стране, в которой вы находитесь.
Используйте CLLocationManager
для получения текущего местоположения и CLGeocoder
для выполнения обратного геокодирования. Вы можете получить название страны отсюда.
Ответ 2
NSString *countryCode = [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode];
предоставит вам идентификатор, например, например. "США" (США), "ES" (Испания) и т.д.
В Swift 3:
let countryCode = NSLocale.current.regionCode
В Swift 2.2:
let countryCode = NSLocale.currentLocale().objectForKey(NSLocaleCountryCode) as String
По сравнению с решением, основанным на CLLocationManager, этот подход имеет свои плюсы и минусы. Основной принцип состоит в том, что он не гарантирует, что это физическое устройство, если пользователь настраивает его по-разному. Это, однако, можно также рассматривать как профессионал, поскольку вместо этого показывает, в какой стране пользователь находится в умственном и культурном отношении - так, если, например, Я уезжаю за границу в отпуск, тогда местность по-прежнему отправляется в мою родную страну. Однако довольно большой профессионал в том, что этот API не требует разрешения пользователя, например CLLocationManager. Поэтому, если вы еще не получили разрешение на использование местоположения пользователя, и вы не можете действительно оправдывать вскрытие всплывающего диалогового окна на лице пользователя (или они уже отклонили это всплывающее окно, и вам нужна резервная копия), то это, вероятно, API, который вы хотите использовать. Некоторыми типичными примерами использования для этого может быть персонализация (например, культурно релевантный контент, форматы по умолчанию и т.д.) И аналитика.
Ответ 3
@Ответ Дениса хорош - вот какой-то код, воплощающий его ответ на практике. Это для настраиваемого класса, который вы настроили на соответствие протоколу 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]);
}];
}
Ответ 4
Здесь альтернативный, возможно, слишком обходный метод. Другие решения основаны на ручных настройках (NSLocale) или при запросе разрешения на использование служб определения местоположения, которые могут быть лишены (CLLocationManager), поэтому у них есть недостатки.
Вы можете получить текущую страну на основе локального часового пояса. Мое приложение взаимодействует с сервером, на котором запущен Python с установленным pytz, и этот модуль предоставляет словарь кодов стран для строк часового пояса. Мне действительно нужно, чтобы сервер знал страну, поэтому мне не нужно настраивать ее полностью на 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.
Если вы создаете версию словаря iOS, доступную в pytz или каком-либо другом источнике, вы можете использовать ее для немедленного поиска кода страны без помощи сервера, основываясь на настройках часового пояса, которые часто бывают актуальными.
Возможно, я ошибаюсь в NSLocale. Предоставляет ли он код страны с помощью региональных настроек форматирования или настроек часового пояса? Если последнее, то это всего лишь более сложный способ получить тот же результат...
Ответ 5
Ниже приведены ответы @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
!
Ответ 6
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
Ответ 7
Для Swift 3 это еще проще:
let countryCode = Locale.current.regionCode
Ответ 8
Вы можете получить NSTimeZone из CLLocation: https://github.com/Alterplay/APTimeZones и работает локально.
Ответ 9
Если вас интересуют только телефонные аппараты, то упомянутая здесь техника может быть вам полезна: Определить страну пользователя iPhone
Ответ 10
Здесь быстрый цикл в Swift 3, который возвращает полный список кодов стран.
let countryCode = NSLocale.isoCountryCodes
for country in countryCode {
print(country)
}