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



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



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



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

555   12  

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

для Swift 3 это еще проще:

let countryCode = Locale.current.regionCode

вы можете получить 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

    Ничего не найдено.