web-dev-qa-db-fra.com

iPhone - Obtenez le nom de la ville à partir de la latitude et de la longitude

Je veux obtenir mon nom de ville actuelle dans mon application iPhone.

Je reçois actuellement la latitude et la longitude en utilisant CLLocationManager et je passe mes coordonnées dans CLGeocoder.

    CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
    [geoCoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
        for (CLPlacemark * placemark in placemarks) {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Current City" message:[NSString stringWithFormat:@"Your Current City:%@",[placemark locality]] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil];
            [alert  show];
        }  
    }];

Cela fonctionne bien sous iOS 5.0 mais ne fonctionne pas sous iOS 4.3.

Au lieu de cela, j'ai commencé à utiliser le service Web de Google. 

-(void)findLocationFor:(NSString *)latitudeStr 
          andLontitude:(NSString *)longtitudeStr{
    if ([self connectedToWiFi]){
        float latitude  = [latitudeStr floatValue];
        float longitude = [longtitudeStr floatValue];
        NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithObjectsAndKeys: 
                                           [NSString stringWithFormat:@"%f,%f", latitude, longitude], @"latlng", nil];
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://maps.googleapis.com/maps/api/geocode/json"]];
        [parameters setValue:@"true" forKey:@"sensor"];
        [parameters setValue:[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode] forKey:@"language"];
        NSMutableArray *paramStringsArray = [NSMutableArray arrayWithCapacity:[[parameters allKeys] count]];

        for(NSString *key in [parameters allKeys]) {
            NSObject *paramValue = [parameters valueForKey:key];
            [paramStringsArray addObject:[NSString stringWithFormat:@"%@=%@", key, paramValue]];
        }

        NSString *paramsString = [paramStringsArray componentsJoinedByString:@"&"];
        NSString *baseAddress = request.URL.absoluteString;
        baseAddress = [baseAddress stringByAppendingFormat:@"?%@", paramsString];
        [request setURL:[NSURL URLWithString:baseAddress]];

        NSError        *error    = nil;
        NSURLResponse  *response = nil;
        NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
        if (response == nil) {
            if (error != nil) {
            }
        }
        else {
            NSDictionary *responseDict = [returnData objectFromJSONData];
            NSArray *resultsArray = [responseDict valueForKey:@"results"]; 
            NSMutableArray *placemarksArray = [NSMutableArray arrayWithCapacity:[resultsArray count]];
            for(NSDictionary *placemarkDict in resultsArray){
                NSDictionary *coordinateDict = [[placemarkDict valueForKey:@"geometry"] valueForKey:@"location"];

                float lat = [[coordinateDict valueForKey:@"lat"] floatValue];
                float lng = [[coordinateDict valueForKey:@"lng"] floatValue];

                NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
                [dict setObject:[NSString stringWithFormat:@"%.f",lat] forKey:@"latitude"];
                [dict setObject:[NSString stringWithFormat:@"%.f",lng] forKey:@"longitude"];
                [dict setObject:[placemarkDict objectForKey:@"formatted_address"] forKey:@"address"];

                [placemarksArray addObject:dict];
                [dict release];
            }
            NSDictionary *placemark = [placemarksArray objectAtIndex:0];
        }
    }
}

Mais la réponse que je reçois est trop longue, ce qui signifie que je ne parviens toujours pas à obtenir le nom de la ville car, dans certains cas, ce service Web donne toutes les autres informations concernant les coordonnées attendues du nom de la ville.

Quelqu'un peut-il m'aider s'il-vous-plaît?

16
Muhammad Saqib

Selon la documentation CLGeocoder ne fonctionne pas sous iOS5. Vous devez prendre un autre chemin pour prendre en charge iOS4 et iOS5.

Vous pouvez regarder MKReverseGeocoder , mais il est déconseillé dans iOS5 mais servira toujours à cette fin. Pour confirmation, vous pouvez vérifier la soi-disant question

+(NSString *)getAddressFromLatLon:(double)pdblLatitude withLongitude:(double)pdblLongitude
{
    NSString *urlString = [NSString stringWithFormat:@"http://maps.google.com/maps/geo?q=%f,%f&output=csv",pdblLatitude, pdblLongitude];
    NSError* error;
    NSString *locationString = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString] encoding:NSASCIIStringEncoding error:&error];
    locationString = [locationString stringByReplacingOccurrencesOfString:@"\"" withString:@""];
    return [locationString substringFromIndex:6];
}

Vous pouvez utiliser cette fonction pour obtenir une adresse à partir de la latitude, de la longitude. Vous pouvez changer selon les besoins. Nous mettons cela comme méthode de classe afin que nous puissions directement l'utiliser comme

NSString *strAddressFromLatLong = [CLassName getAddressFromLatLon:37.484848 withLongitude:74.48489];

EDIT

S'il vous plaît arrêtez d'utiliser la fonction ci-dessus car il a cessé de fonctionner signalé dans les commentaires (non testé par moi). Je recommande de commencer à utiliser SVGeocoder

23
Janak Nirmal

J'utilise ceci et j'obtiens le code postal et le nom de la ville. Modification de la méthode ajoutée par Janak. 

- (void) getAddressFromLatLon:(CLLocation *)bestLocation
{
    NSLog(@"%f %f", bestLocation.coordinate.latitude, bestLocation.coordinate.longitude);
    CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
    [geocoder reverseGeocodeLocation:bestLocation
                   completionHandler:^(NSArray *placemarks, NSError *error)
    {
        if (error){
            NSLog(@"Geocode failed with error: %@", error);
            return;
        }
        CLPlacemark *placemark = [placemarks objectAtIndex:0];
        NSLog(@"placemark.ISOcountryCode %@",placemark.ISOcountryCode);
        NSLog(@"locality %@",placemark.locality);
        NSLog(@"postalCode %@",placemark.postalCode);

    }];

}
13
Ram G.

Ça marche pour moi :) 

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

[ceo reverseGeocodeLocation: loc completionHandler:
 ^(NSArray *placemarks, NSError *error) {
     CLPlacemark *placemark = [placemarks objectAtIndex:0];
     NSLog(@"placemark %@",placemark);
     //String to hold address
     NSString *locatedAt = [[placemark.addressDictionary valueForKey:@"FormattedAddressLines"] componentsJoinedByString:@", "];
     NSLog(@"addressDictionary %@", placemark.addressDictionary);

     NSLog(@"placemark %@",placemark.region);
     NSLog(@"placemark %@",placemark.country);  // Give Country Name
     NSLog(@"placemark %@",placemark.locality); // Extract the city name
     NSLog(@"location %@",placemark.name);
     NSLog(@"location %@",placemark.ocean);
     NSLog(@"location %@",placemark.postalCode);
     NSLog(@"location %@",placemark.subLocality);

     NSLog(@"location %@",placemark.location);
     //Print the location to console
     NSLog(@"I am currently at %@",locatedAt);
 }];
8
Ahmed Mh
//Place below parser code where you are reading latlng and place your latlng in the url
NSXMLParser *parser = [[NSXMLParser alloc]initWithContentsOfURL:[NSURL URLWithString:@"http://maps.googleapis.com/maps/api/geocode/xml?latlng=40.714224,-73.961452&sensor=false"]];
[parser setDelegate:self];
[parser parse];

// Below are the delegates which will get you the exact address easyly
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{    
    if([elementName isEqualToString:@"formatted_address"]){
        got = YES; //got is a BOOL
    }
}

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if(got){
        NSLog(@"the address is = %@",string);
    }
}

-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
}

//what we are doing is using xmlparser to parse the data which we get through the google map api copy above link and use in browser you will see the xml data brought

Désolé pour mon mauvais anglais j'espère que ça vous aidera

5
superGokuN

Essayez cette demande ici, vous trouverez toutes les données sur l'emplacement actuel, le nom de la rue/ville/région, le numéro de rue, mais pour votre demande, collez-le simplement.

NSString *urlString = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false",pdblLatitude, pdblLongitude];
NSError* error;
NSString *locationString = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString] encoding:NSASCIIStringEncoding error:&error];

NSData *data = [locationString dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

NSDictionary *dic = [[json objectForKey:kResults] objectAtIndex:0];
NSString *cityName = [[[dic objectForKey:@"address_components"] objectAtIndex:1] objectForKey:@"long_name"];
3

C'est bien, a travaillé pour moi.

Je reçois la latitude et la longitude en utilisant CLLocationManager et je passe mes coordonnées dans CLGeocoder.

import @corelocation  and for getting city,country #import <AddressBook/AddressBook.h>
    -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
    {
    CLLocation *location=[locations lastObject];
        CLGeocoder *geocoder=[[CLGeocoder alloc]init];

        CLLocationCoordinate2D coord;
        coord.longitude = location.coordinate.longitude;
        coord.latitude = location.coordinate.latitude;
        // or a one shot fill
        coord = [location coordinate];
        NSLog(@"longitude value%f", coord.longitude);
        NSLog(@"latitude value%f", coord.latitude);
        [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
            CLPlacemark *placemark = placemarks[0];
            NSDictionary *addressDictionary = [placemark addressDictionary];
            city = addressDictionary[(NSString *)kABPersonAddressCityKey];
            stateloc = addressDictionary[(NSString *)kABPersonAddressStateKey];
            country = placemark.country;


            NSLog(@"city%@/state%@/country%@",city,stateloc,country);
           [self getImagesFromServer:city];

        }];

        [self stopSignificantChangesUpdates];

    }

- (void)stopSignificantChangesUpdates
{
    [self.locationManager stopUpdatingLocation];
    self.locationManager = nil;
}
2
Shangari C

J'ai trouvé @Constantin Saulenco une excellente réponse: Les résultats ne sont pas toujours ordonnés dans le même ordre - la ville n'est donc pas toujours au même index - cette fonction cherchera le bon. ainsi que.

NSString *urlString = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false",location.coordinate.latitude, location.coordinate.longitude];
NSError* error;
NSString *locationString = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString] encoding:NSASCIIStringEncoding error:&error];

NSData *data = [locationString dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

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

}

NSString* locationFinal = [NSString stringWithFormat:@"%@,%@",cityName,countryName];
1
DaNLtR
- (void)reverseGeocode:(CLLocation *)location {
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
    NSLog(@"Finding address");
    if (error) {
        NSLog(@"Error %@", error.description);
    } else {
        CLPlacemark *placemark = [placemarks lastObject];
        self.myAddress.text = [NSString stringWithFormat:@"%@", ABCreateStringWithAddressDictionary(placemark.addressDictionary, NO)];
    }
}];
}
1
iKushal

J'ai trouvé ce code et cela a fonctionné pour moi: https://Gist.github.com/flyworld/4222448 .

Il suffit de changer placemark.ISOcountryCode en placemark.locality.

0
Carlos Ancona

S'il vous plaît vérifier la fonction ci-dessous

func getDataCity(tmpLat:Double,tmpLong:Double) {

    let tmpCLGeocoder = CLGeocoder.init()
    if tmpLat > 0 , tmpLong > 0
    {
        let tmpDataLoc = CLLocation.init(latitude: tmpLat, longitude: tmpLong)

        tmpCLGeocoder.reverseGeocodeLocation(tmpDataLoc, completionHandler: {(placemarks,error) in

            guard let tmpPlacemarks = placemarks else{
                return
            }
            let placeMark = tmpPlacemarks[0] as CLPlacemark

            guard let strLocality = placeMark.locality else{
                return
            }
            // strLocality is your city
            guard let strSubLocality = placeMark.subLocality else{

                return
            }
            // strSubLocality is your are of city
        })
    }
}
0
Urvish Modi