Подтвердить что ты не робот

Получить местоположение устройства (только страны) в iOS

Мне нужно получить расположение в стране устройства iOS.

Я пытаюсь использовать CoreLocation с MKReverseGeocoder. Однако это, как представляется, довольно часто возвращается. И мне нужна только страна, нет необходимости в улицах и т.д.

Как это можно сделать более стабильным образом?

4b9b3361

Ответ 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

Ответ 10

Здесь быстрый цикл в Swift 3, который возвращает полный список кодов стран.

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