77 Stimmen

Holen Sie sich den Gerätestandort (nur Land) in iOS

Ich muss den Länderstandort eines iOS-Geräts erhalten.

Ich habe versucht, CoreLocation mit MKReverseGeocoder zu verwenden. Dies scheint jedoch häufig fehlerhaft zurückzugeben. Und ich benötige nur das Land, keine Straßen und dergleichen.

Wie kann dies auf stabilere Weise erreicht werden?

116voto

Martin Gjaldbaek Punkte 2897
NSString *countryCode = [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode];

liefert Ihnen einen Bezeichner wie z.B. "US" (Vereinigte Staaten), "ES" (Spanien), etc.


In Swift 3:

let countryCode = NSLocale.current.regionCode

In Swift 2.2:

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

Verglichen mit einer Lösung, die auf CLLocationManager basiert, hat dieser Ansatz Vor- und Nachteile. Der Hauptnachteil besteht darin, dass dies nicht garantiert, dass dies der tatsächliche Standort des Geräts ist, wenn der Benutzer es anders konfiguriert. Dies kann jedoch auch als Vorteil gesehen werden, da es stattdessen zeigt, mit welchem Land ein Benutzer geistig/kulturell verbunden ist - also wenn ich z.B. im Urlaub ins Ausland gehe, ist die Gebietsschema immer noch auf mein Heimatland eingestellt. Ein ziemlich großer Vorteil ist jedoch, dass diese API keine Benutzerberechtigung erfordert, wie es bei CLLocationManager der Fall ist. Wenn Sie also noch keine Erlaubnis zum Verwenden des Standorts des Benutzers erhalten haben und nicht wirklich rechtfertigen können, einen Popup-Dialog dem Benutzer vorzulegen (oder wenn sie diesen Popup bereits abgelehnt haben und Sie eine Alternative benötigen), dann ist dies wahrscheinlich die API, die Sie verwenden möchten. Einige typische Anwendungsfälle hierfür könnten Personalisierung (z.B. kulturell relevante Inhalte, Standardformate etc.) und Analysen sein.

48voto

Denis Punkte 6203

NSLocale ist nur eine Einstellung über die aktuell verwendeten regionalen Einstellungen, es bedeutet nicht das tatsächliche Land, in dem man sich befindet.

Verwende CLLocationManager, um den aktuellen Standort zu erhalten und CLGeocoder, um die Umgekehrte Geocodierung durchzuführen. Du kannst den Ländernamen von dort erhalten.

15voto

Matt Punkte 1081

Die Antwort von @Denis ist gut - hier ist etwas Code, der seine Antwort in die Praxis umsetzt. Dies ist für eine benutzerdefinierte Klasse, die Sie so festgelegt haben, dass sie dem CLLocationManagerDelegate-Protokoll entspricht. Es ist etwas vereinfacht (z.B. wenn der Ortungsmanager mehrere Standorte zurückgibt, wird einfach der erste verwendet), sollte aber den Leuten einen guten Startpunkt liefern...

- (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(@"Aktuelles Land: %@", [self.currentLocPlacemark country]);
        NSLog(@"Aktueller Ländercode: %@", [self.currentLocPlacemark ISOcountryCode]);
    }];
}

13voto

lindanordstrom Punkte 361

Hier sind die Antworten von @Denis und @Matt für eine Swift 3 Lösung zusammengefasst:

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")
        }
    }
}

Vergessen Sie nicht, die NSLocationAlwaysUsageDescription oder NSLocationWhenInUseUsageDescription in der Info.plist festzulegen!

10voto

grep Punkte 556

Wie von @Denis erwähnt, ist Locale nur eine Einstellung zu den aktuell verwendeten regionalen Einstellungen, es bedeutet nicht das tatsächliche Land, in dem du dich befindest.

Die empfohlene Verwendung von CLLocationManager zur Ermittlung des aktuellen Standorts und von CLGeocoder zur Durchführung einer Reverse-Geocodierung bedeutet, dass der Benutzer um Zugriff auf den Standortdienst gebeten wird.

Wie wäre es mit dem Abrufen des Ländercodes vom Mobilfunkanbieter?

import CoreTelephony

guard carrier = CTTelephonyNetworkInfo().subscriberCellularProvider else {
    //iPad
    return
}

let countryST = carrier.isoCountryCode!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X