Получить местоположение устройства (только страна) в iOS - PullRequest
57 голосов
/ 16 декабря 2011

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

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

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

Ответы [ 12 ]

93 голосов
/ 16 декабря 2011
NSString *countryCode = [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode];

даст вам идентификатор, например, например. «США» (США), «ЭС» (Испания) и др.


В Swift 3 :

let countryCode = NSLocale.current.regionCode

In Swift 2.2 :

let countryCode = NSLocale.currentLocale().objectForKey(NSLocaleCountryCode) as String

По сравнению с решением на основе CLLocationManager этот подход имеет свои плюсы и минусы. Основным недостатком является то, что это не гарантирует, что это то, где устройство находится физически, если пользователь настраивает его по-другому. Однако это также можно рассматривать как профессионал, поскольку вместо этого он показывает, с какой страной пользователь умственно / культурно настроен, например, если, например, Я уезжаю за границу на каникулы, тогда местность все еще находится в моей родной стране. Однако довольно большой профессионал в том, что этот API не требует разрешения пользователя, как CLLocationManager. Так что, если вы еще не получили разрешение на использование местоположения пользователя, и вы не можете оправдать появление всплывающего диалогового окна на лице пользователя (или они уже отклонили это всплывающее окно, и вам нужен запасной вариант), то это, вероятно, API хочу использовать. Некоторыми типичными вариантами использования для этого могут быть персонализация (например, контент, относящийся к культуре, форматы по умолчанию и т. Д.) И аналитика.

40 голосов
/ 16 декабря 2011

NSLocale - это просто настройка используемых в настоящее время региональных настроек, это не означает фактическую страну, в которой вы находитесь.

Используйте CLLocationManager, чтобы получить текущее местоположение, и CLGeocoder, чтобы выполнить обратное.-geocoding.Вы можете получить название страны оттуда.

15 голосов
/ 30 мая 2014

@ Ответ Дениса хорош - вот код, который применяет его ответ на практике. Это для пользовательского класса, который вы установили для соответствия протоколу 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]);
    }];
}
11 голосов
/ 29 декабря 2016

Вот ответы @ Дениса и @ Мэтта, составленные для решения 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!

7 голосов
/ 20 июля 2012

Вот альтернативный, возможно, чрезмерно обходной метод. Другие решения основаны на ручных настройках (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 голосов
/ 17 марта 2015
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
3 голосов
/ 06 декабря 2016

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

let countryCode = Locale.current.regionCode
1 голос
/ 23 октября 2013

Вы можете получить NSTimeZone от CLLocation: https://github.com/Alterplay/APTimeZones и работает локально.

0 голосов
/ 18 сентября 2018

Код 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"), необязательно ("Нигерия"). // для региона Нигерии установлено

0 голосов
/ 21 мая 2018

@ Rob

let locale = Locale.current
let code = (locale as NSLocale).object(forKey: NSLocale.Key.countryCode) as! String?

, используя этот код, вы получите код страны своего региона, а если вы не получили его, измените его, просто зайдите в Настройки телефона-> общие-> язык и регион и установите нужный регион

...