Wie kann ich den aktuellen Städtenamen des Benutzers abrufen?

Antworten:

107

Was Sie tun müssen, ist ein Setup CLLocationManager, das Ihre aktuellen Koordinaten findet. Mit den aktuellen Koordinaten müssen Sie MKReverseGeoCoderIhren Standort finden.

- (void)viewDidLoad 
{  
    // this creates the CCLocationManager that will find your current location
    CLLocationManager *locationManager = [[[CLLocationManager alloc] init] autorelease];
    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
    [locationManager startUpdatingLocation];
}

// this delegate is called when the app successfully finds your current location
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
{
    // this creates a MKReverseGeocoder to find a placemark using the found coordinates
    MKReverseGeocoder *geoCoder = [[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate];
    geoCoder.delegate = self;
    [geoCoder start];
}

// this delegate method is called if an error occurs in locating your current location
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error 
{
 NSLog(@"locationManager:%@ didFailWithError:%@", manager, error);
}

// this delegate is called when the reverseGeocoder finds a placemark
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark
{
    MKPlacemark * myPlacemark = placemark;
    // with the placemark you can now retrieve the city name
    NSString *city = [myPlacemark.addressDictionary objectForKey:(NSString*) kABPersonAddressCityKey];
}

// this delegate is called when the reversegeocoder fails to find a placemark
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error
{
    NSLog(@"reverseGeocoder:%@ didFailWithError:%@", geocoder, error);
}
tony.tc.leung
quelle
9
Ein Hinweis: Sie müssen den Standortmanager in einem Ivar aufbewahren (und ihn möglicherweise erneut stoppen, sobald Sie einen Standort erhalten haben). Andernfalls wird er sofort automatisch freigegeben und Sie erhalten keine Rückrufe von Delegierten. Für den Reverse Geocoder ist außerdem eine Internetverbindung erforderlich.
uliwitness
Können Sie mir sagen, wie man die aktuelle Stadt oder den aktuellen Ort in Titel und Untertitel auf Pin druckt?
Raju
1
@Frade #import <AddressBook / AddressBook.h>
Jonathan
18
MKReverseGeoCoder ist seit ios 5.0
adhg
Frade, ich wünschte du hättest sagen können was du herausgefunden hast ... seufz
David
122

Ab iOS 5 MKReverseGeoCoderist veraltet!

So möchten Sie verwenden CLGeocodermit CLLocationManager, sehr einfach und funktioniert mit Block.

Beispiel:

- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation
{
   [self.locationManager stopUpdatingLocation];

   CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
    [geoCoder reverseGeocodeLocation:newLocation
                   completionHandler:^(NSArray *placemarks, NSError *error) {
                       for (CLPlacemark *placemark in placemarks) {
                           .... = [placemark locality];
                       }
                   }];
}

Bearbeiten: Anstelle einer for inSchleife können Sie auch Folgendes tun:

NSString *locString = placemarks.count ? [placemarks.firstObject locality] : @"Not Found";
Marc
quelle
28

Das funktioniert gut für mich:

CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
[geocoder reverseGeocodeLocation:self.locationManager.location
               completionHandler:^(NSArray *placemarks, NSError *error) {
                   NSLog(@"reverseGeocodeLocation:completionHandler: Completion Handler called!");

                   if (error){
                       NSLog(@"Geocode failed with error: %@", error);
                       return;

                   }


                   CLPlacemark *placemark = [placemarks objectAtIndex:0];

                   NSLog(@"placemark.ISOcountryCode %@",placemark.ISOcountryCode);
                   NSLog(@"placemark.country %@",placemark.country);
                   NSLog(@"placemark.postalCode %@",placemark.postalCode);
                   NSLog(@"placemark.administrativeArea %@",placemark.administrativeArea);
                   NSLog(@"placemark.locality %@",placemark.locality);
                   NSLog(@"placemark.subLocality %@",placemark.subLocality);
                   NSLog(@"placemark.subThoroughfare %@",placemark.subThoroughfare);

               }];
Gaurav
quelle
Warum gibt es ein Array zurück? seltsam. Danke trotzdem.
Adam Waite
Das ist glatt, Liebesblöcke. Ich würde eine Bedingung für das Ortsmarken-Array setzen, um sicherzustellen, dass objectatindex: 0 tatsächlich existiert.
Capikaw
4
Hallo, ich erhalte eine Fehlermeldung. kCLErrorDomain error 8Weißt du warum?
Maxisme
CLGeoCoder ist nicht deklariert, was ich tun muss, damit es funktioniert, was importiert und was hinzugefügt werden muss
iOS Developer
16

Wenn jemand versucht, von MKReverseGeocoder auf CLGeocoder umzusteigen, habe ich einen Blog-Beitrag geschrieben, der hilfreich sein könnte: http://jonathanfield.me/jons-blog/clgeocoder-example.html

Grundsätzlich wäre ein Beispiel, nachdem Sie locationManager- und CLGeocoder-Objekte erstellt haben, fügen Sie diesen Code einfach zu viewDidLoad () hinzu und erstellen Sie dann einige Beschriftungen oder Textbereiche, um die Daten anzuzeigen.

  [super viewDidLoad];
    locationManager.delegate = self;
    [locationManager startUpdatingLocation];

    locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
    [self.CLGeocoder reverseGeocodeLocation: locationManager.location completionHandler: 
     ^(NSArray *placemarks, NSError *error) {


         CLPlacemark *placemark = [placemarks objectAtIndex:0];


             isoCountryCode.text = placemark.ISOcountryCode;
             country.text = placemark.country;
             postalCode.text= placemark.postalCode;
             adminArea.text=placemark.administrativeArea;
             subAdminArea.text=placemark.subAdministrativeArea;
             locality.text=placemark.locality;
             subLocality.text=placemark.subLocality;
             thoroughfare.text=placemark.thoroughfare;
             subThoroughfare.text=placemark.subThoroughfare;
             //region.text=placemark.region;



     }];
Jonathan Field
quelle
@macayer Ja, würde abstürzen, wenn es leer ist, wird aber niemals leer sein, wenn ich es richtig verstehe. Enthält entweder 1 oder mehr Elemente oder nilwird und Nachrichten gesendet, um zu nilresultieren nil, sowie Eigenschaftszugriff durch Punktnotation über nil. errorDavon abgesehen sollte man immer prüfen, ob dies nicht der Fall ist nil.
Victor Zamanian
3

Wenn jemand es in Swift 3 braucht , habe ich es so gemacht:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

    let location = locations.first!
    let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, 500, 500)

    self.location = location
    self.locationManager?.stopUpdatingLocation()

    // Drop a pin at user's Current Location
    let myAnnotation: MKPointAnnotation = CustomPointAnnotation()
    myAnnotation.coordinate = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
    myAnnotation.title = "Localização"
    self.mapViewMK.addAnnotation(myAnnotation)

    self.mapViewMK.setRegion(coordinateRegion, animated: true)
    self.locationManager?.stopUpdatingLocation()
    self.locationManager = nil

    // Get user's current location name
    let geocoder = CLGeocoder()
    geocoder.reverseGeocodeLocation(self.location!) { (placemarksArray, error) in

        if (placemarksArray?.count)! > 0 {

            let placemark = placemarksArray?.first
            let number = placemark!.subThoroughfare
            let bairro = placemark!.subLocality
            let street = placemark!.thoroughfare

            self.addressLabel.text = "\(street!), \(number!) - \(bairro!)"
        }
    }
}
Paula Hasstenteufel
quelle
3

Nachdem Sie CLLocationManager eingerichtet haben, erhalten Sie eine Standortaktualisierung als Breiten- / Längengradpaar. Dann können Sie CLGeocoder verwenden, um die Koordinate in einen benutzerfreundlichen Ortsnamen zu konvertieren.

Hier ist der Beispielcode in Swift 4 .

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    if let lastLocation = locations.last {
        let geocoder = CLGeocoder()

        geocoder.reverseGeocodeLocation(lastLocation) { [weak self] (placemarks, error) in
            if error == nil {
                if let firstLocation = placemarks?[0],
                    let cityName = firstLocation.locality { // get the city name
                    self?.locationManager.stopUpdatingLocation()
                }
            }
        }
    }
}
Michael Wang
quelle
2

Sie müssen den aktuellen Standort des Benutzers ermitteln und dann mit MKReverseGeocoder die Stadt erkennen.

Im iPhone App-Programmierhandbuch , Kapitel 8, finden Sie ein hervorragendes Beispiel . Wenn Sie den Standort-Geocoder initialisiert haben, legen Sie den Delegaten fest und lesen Sie das Land von der Ortsmarke. Lesen Sie die Dokumentation zu MKReverseGeocodeDelegate und erstellen Sie Methoden:

  • reverseGeocoder: didFindPlacemark:
  • reverseGeocoder: didFailWithError:

    MKReverseGeocoder *geocoder = [[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate];
    geocoder.delegate = self;
    [geocoder start];
    
Marcin Zbijowski
quelle
1

Mit diesem Code können Sie die aktuelle Stadt abrufen: -

Erweiterung YourController: CLLocationManagerDelegate {func locationManager (Manager: CLLocationManager, didUpdateLocations-Speicherorte: [CLLocation]) {

    CLGeocoder().reverseGeocodeLocation(manager.location!, completionHandler: {(placemarks, error)->Void in

        if (error != nil)
        {
            manager.stopUpdatingLocation()
            return
        }
        else
        {
            if placemarks!.count > 0
            {
                let placeMarksArrray: NSArray = placemarks!
                let pm = placeMarksArrray[0] as! CLPlacemark
                self.displayLocationInfo(pm)
                manager.stopUpdatingLocation()
            } else
            {
                print("Problem with the data received from geocoder")
            }
        }
    })
}

func displayLocationInfo(placemark: CLPlacemark!) {
    if (placemark != nil) {
        //stop updating location to save battery life
        locationLocation.stopUpdatingLocation()
        var tempString : String = ""
        if(placemark.locality != nil){
            tempString = tempString +  placemark.locality! + " "
            print(placemark.locality)
        }
        if(placemark.postalCode != nil){
            tempString = tempString +  placemark.postalCode! + " "
            print(placemark.postalCode)
        }
        if(placemark.administrativeArea != nil){
            tempString = tempString +  placemark.administrativeArea! + " "
            print(placemark.administrativeArea)
        }
        if(placemark.country != nil){
            tempString = tempString +  placemark.country! + " "



        }
        let dictForaddress = placemark.addressDictionary as! NSDictionary


        if let city = dictForaddress["City"] {
            print(city)



        }
        strLocation = tempString
    }
}
Anand Kr. Avasthi
quelle
0
// place the function code below in desire location in program.

// [self getCurrentLocation];



-(void)getCurrentLocation
{
    CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
    [geocoder reverseGeocodeLocation:self->locationManager.location
                   completionHandler:^(NSArray *placemarks, NSError *error) {
                       NSLog(@"reverseGeocodeLocation:completionHandler: Completion Handler called!");

                       if (error){
                           NSLog(@"Geocode failed with error: %@", error);
                           return;

                       }


                       CLPlacemark *placemark = [placemarks objectAtIndex:0];

                       NSLog(@"placemark.ISOcountryCode %@",placemark.ISOcountryCode);
                       NSLog(@"placemark.country %@",placemark.country);
                        NSLog(@"placemark.locality %@",placemark.locality );
                       NSLog(@"placemark.postalCode %@",placemark.postalCode);
                       NSLog(@"placemark.administrativeArea %@",placemark.administrativeArea);
                       NSLog(@"placemark.locality %@",placemark.locality);
                       NSLog(@"placemark.subLocality %@",placemark.subLocality);
                       NSLog(@"placemark.subThoroughfare %@",placemark.subThoroughfare);

                   }];
}
Robert William Clancy
quelle
0

Hier ist meine kleine Swift-Klasse, die mir hilft, umgekehrte geokodierte Informationen über den aktuellen Standort zu erhalten. Vergessen Sie nicht das NSLocationWhenInUseUsageDescriptionFeld in Info.plist.

class CurrentPlacemarkUpdater: NSObject, CLLocationManagerDelegate {

    private let locationManager = CLLocationManager()
    private let geocoder = CLGeocoder()

    private(set) var latestPlacemark: CLPlacemark?
    var onLatestPlacemarkUpdate: (() -> ())?
    var shouldStopOnUpdate: Bool = true

    func start() {
        locationManager.requestWhenInUseAuthorization()
        locationManager.desiredAccuracy = kCLLocationAccuracyKilometer
        locationManager.delegate = self
        locationManager.startUpdatingLocation()
    }

    func stop() {
        locationManager.stopUpdatingLocation()
    }

    fileprivate func updatePlacemark(for location: CLLocation) {
        geocoder.reverseGeocodeLocation(location) { [weak self] placemarks, error in
            if let placemark = placemarks?.first {
                self?.latestPlacemark = placemark
                self?.onLatestPlacemarkUpdate?()
                if self?.shouldStopOnUpdate ?? false {
                    self?.stop()
                }
            }
        }
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        if let location = locations.last {
            updatePlacemark(for: location)
        }
    }

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("CurrentPlacemarkUpdater: \(error)")
    }

}
Timur Bernikovich
quelle
-10

Lesen Sie die Dokumentation zu MKReverseGeocoder - die Dokumentation, Anleitungen und Beispielanwendungen werden von Apple aus einem bestimmten Grund bereitgestellt.

Nathan de Vries
quelle
2
MKReverseGeoCoder ist veraltet
Marc