How to retrieve user's current city name?

IphoneObjective CCore Location

Iphone Problem Overview


How do you retrieve the user's current city name?

Iphone Solutions


Solution 1 - Iphone

As of iOS 5 MKReverseGeoCoder is Deprecated!

So you want to use CLGeocoder with CLLocationManager, very simple and works with block.

Example:

- (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: Instead of a for in loop you can also do:

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

Solution 2 - Iphone

What you have to do is setup a CLLocationManager that will find your current coordinates. With the current coordinates you need to use MKReverseGeoCoder to find your location.

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

Solution 3 - Iphone

This is working fine for me :

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

               }];

Solution 4 - Iphone

If anyone is trying to move onto CLGeocoder from MKReverseGeocoder then I have written a blog post that might be of help <http://jonathanfield.me/jons-blog/clgeocoder-example.html>

Basically an example would be, after you have created locationManager and CLGeocoder objects just add this code to your viewDidLoad() and then make some labels or text areas to show the 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;
             
             
         
     }];

Solution 5 - Iphone

After you setup CLLocationManager you would get location update as a latitude/longitude pair. Then you could use CLGeocoder to convert the coordinate to a user friendly place name.

Here is the sample code 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()
                }
            }
        }
    }
}

Solution 6 - Iphone

If anyone needs it in Swift 3, this is how I did it:

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

Solution 7 - Iphone

You have to get user's current location and then use MKReverseGeocoder to recognize the city.

There's great example in iPhone App Programming Guide, chapter 8. Once you've got location initialize geocoder, set the delegate and read country from the placemark. Read the documentation for MKReverseGeocodeDelegate and create methods:

  • reverseGeocoder:didFindPlacemark:

  • reverseGeocoder:didFailWithError:

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

Solution 8 - Iphone

You can use this code for getting Current City:--

extension 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
    }
}

Solution 9 - Iphone

Here is my small Swift class which helps me with getting reverse geocoded information about current location. Don't forget about NSLocationWhenInUseUsageDescription field 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)")
    }

}

Solution 10 - Iphone

// 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);
                       
                   }];
}

Solution 11 - Iphone

Read the documentation for MKReverseGeocoder -- the documentation, guides & sample applications are provided by Apple for a reason.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSandeep KumarView Question on Stackoverflow
Solution 1 - IphoneMarcView Answer on Stackoverflow
Solution 2 - Iphonetony.tc.leungView Answer on Stackoverflow
Solution 3 - IphoneGauravView Answer on Stackoverflow
Solution 4 - IphoneJonathan FieldView Answer on Stackoverflow
Solution 5 - IphoneMichael WangView Answer on Stackoverflow
Solution 6 - IphonePaula HasstenteufelView Answer on Stackoverflow
Solution 7 - IphoneMarcin ZbijowskiView Answer on Stackoverflow
Solution 8 - IphoneAnand Kr. AvasthiView Answer on Stackoverflow
Solution 9 - IphoneTimur BernikovichView Answer on Stackoverflow
Solution 10 - IphoneRobert William ClancyView Answer on Stackoverflow
Solution 11 - IphoneNathan de VriesView Answer on Stackoverflow