จะดึงชื่อเมืองปัจจุบันของผู้ใช้ได้อย่างไร?


คำตอบ:


107

สิ่งที่คุณต้องทำคือตั้งค่าCLLocationManagerที่จะค้นหาพิกัดปัจจุบันของคุณ ด้วยพิกัดปัจจุบันคุณต้องใช้MKReverseGeoCoderเพื่อค้นหาตำแหน่งของคุณ

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

9
หมายเหตุประการหนึ่ง: คุณต้องซ่อนผู้จัดการสถานที่ไว้ใน ivar (และอาจหยุดอีกครั้งเมื่อคุณได้รับตำแหน่ง) มิฉะนั้นจะถูกปล่อยอัตโนมัติทันทีและคุณจะไม่ได้รับการติดต่อกลับจากตัวแทน นอกจากนี้ geocoder ย้อนกลับต้องใช้การเชื่อมต่ออินเทอร์เน็ตเพื่อให้ทำงานได้
uliwitness

คุณช่วยบอกฉันได้ไหมว่าจะพิมพ์เมืองหรือตำแหน่งปัจจุบันในชื่อเรื่องและคำบรรยายบนพินได้อย่างไร ???
Raju

1
@Frade #import <AddressBook / AddressBook.h>
Jonathan

18
MKReverseGeoCoder เลิกใช้ตั้งแต่ iOS 5.0
adhg

Frade ฉันหวังว่าคุณจะได้พูดในสิ่งที่คุณพบ ... ถอนหายใจ
David

122

เนื่องจาก iOS 5 MKReverseGeoCoderเลิกใช้งานแล้ว!

ดังนั้นคุณจึงต้องการที่จะใช้CLGeocoderกับCLLocationManagerง่ายมากและทำงานร่วมกับบล็อก

ตัวอย่าง:

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

แก้ไข:แทนที่จะfor inวนซ้ำคุณสามารถทำได้:

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

28

สิ่งนี้ใช้ได้ดีสำหรับฉัน:

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);

               }];

เหตุใดจึงส่งคืนอาร์เรย์ แปลก. ขอบคุณต่อไป
Adam Waite

นี่มันเนียนเลิฟบล็อค ฉันจะวางเงื่อนไขให้กับอาร์เรย์หมุดเพื่อให้แน่ใจว่า objectatindex: 0 มีอยู่จริง
capikaw

4
สวัสดีฉันได้รับข้อผิดพลาดkCLErrorDomain error 8คุณรู้หรือไม่ว่าทำไม?
maxisme

CLGeoCoder ไม่ได้ประกาศว่าฉันต้องทำอะไรดังนั้นจึงอาจใช้งานได้ว่าจะนำเข้าอะไรและต้องเพิ่มอะไรบ้าง
นักพัฒนา iOS

17

หากใครกำลังพยายามย้ายเข้าสู่ CLGeocoder จาก MKReverseGeocoder ฉันได้เขียนบล็อกโพสต์ที่อาจช่วยได้http://jonathanfield.me/jons-blog/clgeocoder-example.html

โดยทั่วไปตัวอย่างจะเป็นหลังจากที่คุณสร้าง locationManager และวัตถุ CLGeocoder เพียงแค่เพิ่มรหัสนี้ใน viewDidLoad () ของคุณแล้วสร้างป้ายกำกับหรือพื้นที่ข้อความเพื่อแสดงข้อมูล

  [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;



     }];

@macayer ใช่จะพังถ้าว่าง แต่จะไม่ว่างถ้าฉันเข้าใจถูกต้อง อาจจะมี 1 หรือมากกว่าองค์ประกอบหรือnilและข้อความที่ส่งไปnilมีผลในการเช่นเดียวกับการเข้าถึงสถานที่ให้บริการผ่านจุดสัญกรณ์ผ่านnil nilที่ถูกกล่าวว่าหนึ่งควรตรวจสอบว่าเป็นที่ไม่ใช่error nil
Victor Zamanian

5

หลังจากที่คุณตั้งค่า CLLocationManager คุณจะได้รับการอัปเดตตำแหน่งเป็นคู่ละติจูด / ลองจิจูด จากนั้นคุณสามารถใช้ CLGeocoder เพื่อแปลงพิกัดเป็นชื่อสถานที่ที่ใช้งานง่าย

นี่คือตัวอย่างรหัสในสวิฟท์ 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()
                }
            }
        }
    }
}

3

หากใครต้องการมันในSwift 3นี่คือวิธีที่ฉันทำ:

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

2

คุณต้องได้รับตำแหน่งปัจจุบันของผู้ใช้จากนั้นใช้ MKReverseGeocoder เพื่อจดจำเมือง

มีตัวอย่างที่ยอดเยี่ยมในคู่มือการเขียนโปรแกรมแอพ iPhoneบทที่ 8 เมื่อคุณได้ตำแหน่งเริ่มต้น geocoder แล้วให้ตั้งค่าผู้รับมอบสิทธิ์และอ่านประเทศจากหมุด อ่านเอกสารสำหรับ MKReverseGeocodeDelegate และสร้างเมธอด:

  • reverseGeocoder: didFindPlacemark:
  • reverseGeocoder: didFailWithError:

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

1

คุณสามารถใช้รหัสนี้เพื่อรับเมืองปัจจุบัน: -

ส่วนขยาย 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
    }
}

1

นี่คือคลาส Swift ขนาดเล็กของฉันซึ่งช่วยฉันในการรับข้อมูลพิกัดภูมิศาสตร์ย้อนกลับเกี่ยวกับตำแหน่งปัจจุบัน อย่าลืมเกี่ยวกับข้อมูลในNSLocationWhenInUseUsageDescriptionInfo.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)")
    }

}

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);

                   }];
}

-10

อ่านเอกสารสำหรับMKReverseGeocoder - เอกสารคำแนะนำและแอปพลิเคชันตัวอย่างจัดเตรียมโดย Apple ด้วยเหตุผล


2
MKReverseGeoCoder เลิกใช้แล้ว
Marc
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.