Bagaimana cara mendapatkan kembali nama kota pengguna saat ini?

Jawaban:

107

Yang harus Anda lakukan adalah menyiapkan a CLLocationManageryang akan menemukan koordinat Anda saat ini. Dengan koordinat saat ini yang perlu Anda gunakan MKReverseGeoCoderuntuk menemukan lokasi Anda.

- (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
sumber
9
Satu catatan: Anda harus menyimpan pengelola lokasi di ivar (dan mungkin menghentikannya lagi setelah Anda menerima lokasi), jika tidak maka akan segera dirilis secara otomatis dan Anda tidak akan menerima panggilan balik delegasi. Selain itu, geocoder terbalik memerlukan koneksi internet agar berfungsi.
uliwitness
Bisakah Anda memberi tahu saya cara mencetak Kota atau Lokasi Saat Ini dalam Judul dan Subtitle di Pin ???
Raju
1
@Frade #import <AddressBook / AddressBook.h>
Jonathan
18
MKReverseGeoCoder tidak digunakan lagi sejak ios 5.0
adhg
Frade, kuharap kau bisa mengatakan apa yang kau temukan ... sigh
David
122

Sejak iOS 5 MKReverseGeoCoderTidak Berlaku Lagi!

Jadi Anda ingin menggunakan CLGeocoderdengan CLLocationManagersangat sederhana dan bekerja dengan blok.

Contoh:

- (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];
                       }
                   }];
}

Edit: Alih-alih for inlingkaran Anda juga dapat melakukan:

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

Ini berfungsi dengan baik untuk saya:

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
sumber
Mengapa mengembalikan array? aneh. Terima kasih.
Adam Waite
Ini licin, blok cinta. Saya akan memberi syarat pada larik penanda letak untuk memastikan objectatindex: 0 benar-benar ada.
capikaw
4
Halo, saya mendapatkan kesalahan, kCLErrorDomain error 8tahukah Anda mengapa?
maxisme
CLGeoCoder tidak menyatakan apa yang harus saya lakukan sehingga mungkin berhasil apa yang harus diimpor dan apa yang harus ditambahkan
Pengembang iOS
17

Jika ada yang mencoba pindah ke CLGeocoder dari MKReverseGeocoder maka saya telah menulis posting blog yang mungkin bisa membantu http://jonathanfield.me/jons-blog/clgeocoder-example.html

Pada dasarnya contohnya adalah, setelah Anda membuat objek locationManager dan CLGeocoder cukup tambahkan kode ini ke viewDidLoad () Anda dan kemudian buat beberapa label atau area teks untuk menampilkan data.

  [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
sumber
@macayer Ya, akan macet jika kosong, tetapi tidak akan pernah kosong jika saya mengerti dengan benar. Akan berisi 1 atau lebih elemen atau menjadi nil, dan pesan yang dikirim ke nilhasil nil, serta akses properti melalui notasi titik melalui nil. Yang sedang berkata, seseorang harus selalu memeriksa apakah errorbukan- nil.
Victor Zamanian
4

Setelah Anda menyiapkan CLLocationManager, Anda akan mendapatkan pembaruan lokasi sebagai pasangan garis lintang / bujur. Kemudian Anda dapat menggunakan CLGeocoder untuk mengubah koordinat menjadi nama tempat yang ramah pengguna.

Berikut ini contoh kode di 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
sumber
3

Jika ada yang membutuhkannya di Swift 3 , inilah cara saya melakukannya:

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
sumber
2

Anda harus mendapatkan lokasi pengguna saat ini dan kemudian menggunakan MKReverseGeocoder untuk mengenali kota tersebut.

Ada contoh bagus di Panduan Pemrograman Aplikasi iPhone , bab 8. Setelah Anda mendapatkan lokasi inisialisasi geocoder, setel delegasi dan baca negara dari tanda letak. Baca dokumentasi untuk MKReverseGeocodeDelegate dan buat metode:

  • reverseGeocoder: didFindPlacemark:
  • reverseGeocoder: didFailWithError:

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

Anda dapat menggunakan kode ini untuk mendapatkan Kota Saat Ini: -

ekstensi YourController: CLLocationManagerDelegate {func locationManager (manager: CLLocationManager, didUpdateLocations locations: [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
sumber
1

Ini adalah kelas Swift kecil saya yang membantu saya mendapatkan informasi geocode terbalik tentang lokasi saat ini. Jangan lupa tentang NSLocationWhenInUseUsageDescriptionfield 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
sumber
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
sumber
-10

Baca dokumentasi untuk MKReverseGeocoder - dokumentasi, panduan & contoh aplikasi disediakan oleh Apple karena suatu alasan.

Nathan de Vries
sumber
2
MKReverseGeoCoder sudah ditinggalkan
Marc