0

I want to send the city name to the server. I am getting latitude longitude using CLLocationManager. Then I use this link to do reverse geocoding.

https://maps.googleapis.com/maps/api/geocode/json?latlng=lati,longi&key=myApiKey

My problem is for different locations the number of address components are different. As an example, I am getting this array of address componeents for my current location.

"results": [
    {
        "address_components": [
            {
                "long_name": "ABC Rd", 
                "short_name": "ABC Rd", 
                "types": [
                    "route"
                ]
            }, 
            {
                "long_name": "My City", 
                "short_name": "My City", 
                "types": [
                    "administrative_area_level_2", 
                    "political"
                ]
            }, 
            {
                "long_name": "My Province", 
                "short_name": "AB", 
                "types": [
                    "administrative_area_level_1", 
                    "political"
                ]
            }, 
            {
                "long_name": "My Country", 
                "short_name": "MC", 
                "types": [
                    "country", 
                    "political"
                ]
            }
        ], 

For my client's location im getting this

results": [
    {
        "address_components": [
            {
                "long_name": "4", 
                "short_name": "4", 
                "types": [
                    "street_number"
                ]
            }, 
            {
                "long_name": "some name", 
                "short_name": "some name", 
                "types": [
                    "route"
                ]
            }, 
            {
                "long_name": "some name", 
                "short_name": "Some name", 
                "types": [
                    "political", 
                    "sublocality", 
                    "sublocality_level_2"
                ]
            }, 
            {
                "long_name": "some name", 
                "short_name": "some name", 
                "types": [
                    "political", 
                    "sublocality", 
                    "sublocality_level_1"
                ]
            }, 
            {
                "long_name": "city", 
                "short_name": "city", 
                "types": [
                    "locality", 
                    "political"
                ]
            }, 
            {
                "long_name": "some name", 
                "short_name": "Some name", 
                "types": [
                    "administrative_area_level_1", 
                    "political"
                ]
            }, 
            {
                "long_name": "Client country", 
                "short_name": "CC", 
                "types": [
                    "country", 
                    "political"
                ]
            }, 
            {
                "long_name": "12345", 
                "short_name": "12345", 
                "types": [
                    "postal_code"
                ]
            }
        ], 

How can I get the exact city name for different locations when the address components are different. First I tried to get it my component index number but since number of components are different I cant do that. Whats the correct way to do that? Please help me. Thanks

UPDATE

[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
    NSLog(@"Found placemarks: %@, error: %@", placemarks, error);
    if (error == nil && [placemarks count] > 0) {

        placemark = [placemarks objectAtIndex:0];

        NSString *address = [NSString stringWithFormat:@"%@ %@\n%@ %@\n%@\n%@",
                             placemark.subThoroughfare, placemark.thoroughfare,
                             placemark.postalCode, placemark.subLocality,
                             placemark.subAdministrativeArea,
                            placemark.country];

       // NSString *address=[self.placemark];

        NSDictionary *dictAddress = [NSDictionary dictionaryWithDictionary:placemark.addressDictionary];
        NSMutableDictionary *dictTxtData = [NSMutableDictionary dictionary];
        NSLog(@"----LOCATION NAME----%@",[placemark.addressDictionary valueForKey:@"Name"]);
        NSLog(@"-----STREET ADDRESS---%@",[placemark.addressDictionary valueForKey:@"Thoroughfare"]);
        NSLog(@"-----CITY-----%@",[placemark.addressDictionary valueForKey:@"City"]);



        strCountry=placemark.country;

        NSLog(@"Address------%@",address);
    } else {
        NSLog(@"%@", error.debugDescription);
    }
} ];

Results I get

----LOCATION NAME----My Rd
-----STREET ADDRESS---My Rd
-----CITY-----(null)
Address------(null) My Rd
(null) (null)
(null)
My Country

This is how I call to location update

-(void)GetLocationData
 {
   if (self.locationManager == nil)
   {
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;
}
else
{
    nil;
}

if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])
{
    [self.locationManager requestWhenInUseAuthorization];
}
else
{
    nil;
}

self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;//kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
}
user1960169
  • 3,533
  • 12
  • 39
  • 61
  • Do you have to use use Google or is an Apple-solution fine? – HAS Feb 27 '17 at 06:12
  • http://stackoverflow.com/questions/1382900/how-to-retrieve-users-current-city-name Does that help? – HAS Feb 27 '17 at 06:14
  • I use google api for reverse geocoding – user1960169 Feb 27 '17 at 06:15
  • Yeah I saw that but do you *have* to use it? – HAS Feb 27 '17 at 06:16
  • I tried to use CLGeocoder but it doesnt return any city. Most of the properties comes as null thats why I used google api – user1960169 Feb 27 '17 at 06:17
  • That's weird, can you post the code you used? And did you make sure the location manager returns the correct result? http://stackoverflow.com/questions/21194958/clgeocoder-returns-null-results-for-city-and-state-when-using-current-location-d – HAS Feb 27 '17 at 06:20
  • Can you see my UPDATE part – user1960169 Feb 27 '17 at 06:41
  • Hm, have you tried printing the complete address dictionary and see if the city is in there? If not that's bad, if yes try to use the keys from the contact framework as the documentation suggests or convert the accessor `city` on CLPlacemark (or MKPlacemark) – HAS Feb 27 '17 at 06:47
  • yeas I tried to print but city is not there – user1960169 Feb 27 '17 at 06:51

2 Answers2

1

The json responses from Google API can contain different place marks depending upon the location. Using index is not the correct approach. You can find the city name in json components where type is locality. Below is the code snippet

NSDictionary *locationData = [[json objectForKey:@"results"] objectAtIndex:0];
NSArray* addressComponents= [locationData objectForKey:@"address_components"];
//Iterate each result of address components - find locality and country
NSString *cityName;
   for (NSDictionary* address in addressComponents)
    {
        NSArray* addressType = [address objectForKey:@"types"];
       NSString* firstType = [addressType objectAtIndex:0];
       if([firstType isEqualToString:@"locality"])
           cityName = [address objectForKey:@"long_name"];
}

or you can also use CLGeocoder API in iOS.

CLGeocoder *ceo = [[CLGeocoder alloc]init];
CLLocation *loc = [[CLLocation alloc]initWithLatitude:lat longitude:long];

[ceo reverseGeocodeLocation: loc completionHandler:
 ^(NSArray *placemarks, NSError *error) {
     CLPlacemark *placemark = [placemarks objectAtIndex:0];
     NSLog(@"placemark %@",placemark.locality); // Get the city name
 }];
PK Bhatia
  • 21
  • 3
0

call setLocation() in viewdidload method

func setLocation()
{

    // self.view.backgroundColor = UIColor.whiteColor()
    self.edgesForExtendedLayout = .None

    // Set bounds to inner-west Sydney Australia.



    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestWhenInUseAuthorization()
    locationManager.startUpdatingLocation()



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

    //        print("dofo \(manager.location?.coordinate.latitude)")
    //        print(manager.location?.coordinate.longitude)



        currentlat = (manager.location?.coordinate.latitude)!
        cuurentlong = (manager.location?.coordinate.longitude)!




        let geoCoder = CLGeocoder()
        let location = CLLocation(latitude: currentlat,
                                  longitude: cuurentlong)
        geoCoder.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in

            // Place details
            var placeMark: CLPlacemark!
            placeMark = placemarks?[0]

            // Address dictionary
            print(placeMark.addressDictionary)

            // Location name
            if let locationName = placeMark.addressDictionary!["Name"] as? NSString {
                print(locationName)
            }

            // Street address
            if let street = placeMark.addressDictionary!["Thoroughfare"] as? NSString {
                print(street)
            }

            // City
            if let city = placeMark.addressDictionary!["City"] as? NSString {
                print(city)
            }

            // Zip code
            if let zip = placeMark.addressDictionary!["ZIP"] as? NSString {
                print(zip)
            }

            // Country
            if let country = placeMark.addressDictionary!["Country"] as? NSString {
                print(country)
            }

        })





}
Chetan Hedamba
  • 229
  • 2
  • 7