Вопрос по iphone, objective-c, ios – iPhone - получить название города от широты и долготы

16

Я хочу получить название моего текущего города в приложении для iPhone.

В настоящее время я получаю широту и долготу с помощью CLLocationManager, а затем передаю свои координаты в 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];
        }  
    }];

Это нормально работает в iOS 5.0, но не работает в iOS 4.3.

В качестве альтернативы я начал использовать веб-сервис 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];
        }
    }
}

Но ответ, который я получаю, слишком длинный, означает, что я все еще не могу получить название города, потому что в некоторых случаях этот веб-сервис предоставляет всю другую информацию относительно координат, ожидающих название города.

Кто-нибудь может мне помочь?

Смотрите мой ответ в swift 4.1 Xcode 9.4.1. Вы можете получить даже детали названия деревни также.stackoverflow.com/questions/16647996/… iOS

Ваш Ответ

10   ответов
23

CLGeocoder не работает ниже iOS5. Вам нужно выбрать другой маршрут для поддержки iOS4 и iOS5.

Вы можете посмотреть наMKReverseGeocoderТем не менее, это не рекомендуется в iOS5, но все еще будет служить цели. Для подтверждения вы можете проверитьтак называемый вопрос

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

Вы можете использовать эту функцию для получения адреса по широте, долготе. Вы можете изменить в соответствии с требованием. Мы помещаем это как метод класса, чтобы мы могли напрямую использовать его как

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

EDIT

Пожалуйста, прекратите использовать вышеуказанную функцию, так как она перестала работать, о чем сообщается в комментариях (не проверено мной). Я рекомендую начать использоватьSVGeocoder

@HardikShah Вы получаете этот вывод, потому что вы используетеcsv, Измените это наxml или жеjson лайкoutput=xml он скажет вам, что это старое геокодирование, а новое отличается. Вы также получите новую ссылку геокодирования в ответе xml или json.
Не работает для меня, я использую этоmaps.google.com/maps/geo?q=37.785834,-122.406417&output=csv  Выход составляет «610,0,0,0».
Некоторое время этот код не работает, пожалуйста, попробуйте найти альтернативное решение
8

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

Я получаю широту и долготу с помощью CLLocationManager, а затем передаю свои координаты в 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;
}
1

В результате json не всегда упорядочен в одном и том же порядке - поэтому город не всегда совпадает по индексу - эта функция будет искать правильный. Также добавлена страна.

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];
0

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
        })
    }
}
5

//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

0

https://gist.github.com/flyworld/4222448.

Просто поменяйplacemark.ISOcountryCode вplacemark.locality.

nvm нашел его в яблочных документах ....
1

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

здесь вы найдете все данные о текущем местоположении, название улицы / города / региона, номер дома, но для вашего запроса просто вставьте это.

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"];
Проверьте эту ссылку:maps.googleapis.com/maps/api/geocode/…  Страна возвращается туда, поэтому код не является обобщенным, пожалуйста, проверьте.
Я использую ваше решение, и оно работает отлично, спасибо ..
13

етод, добавленный 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);

    }];

}

Похожие вопросы