Reputation: 991
I want get my Current City name in my iPhone App.
I'm currently getting the latitude and longitude using CLLocationManager and than i am passing my coordinates into 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];
}
}];
This is working fine in iOS 5.0 but not working in iOS 4.3.
As an alternative, I started using the Google Web service
-(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];
}
}
}
But the response which i am getting is too long , means i am still unable to get the city name because in some case this web service give all other information regarding coordinates expect City Name.
Can any one help me please?
Upvotes: 16
Views: 28629
Reputation: 1138
Please check the bellow function
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
})
}
}
Upvotes: 0
Reputation: 67
I found this code and it worked for me: https://gist.github.com/flyworld/4222448.
Just change placemark.ISOcountryCode
to placemark.locality
.
Upvotes: 0
Reputation: 91
It works for me :)
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);
}];
Upvotes: 9
Reputation: 561
I improved @Constantin Saulenco great answer- the json results in not always ordered in same order - so city is not always at the same index - this func will search for the right one. Added country as well.
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];
Upvotes: 1
Reputation: 772
This is fine, worked for me.
I'm getting the latitude and longitude using CLLocationManager and than i am passing my coordinates into 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;
}
Upvotes: 2
Reputation: 2383
Try this request here you will find all data about the current location, street/city/region name, house number but for your request just paste this.
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"];
Upvotes: 3
Reputation: 3125
I am using this and getting the ZIP code and City Name. Modified the method added by 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);
}];
}
Upvotes: 13
Reputation: 2899
- (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)];
}
}];
}
Upvotes: 2
Reputation: 22726
As per documentation CLGeocoder does not work below iOS5. You need to take another route to support iOS4 and iOS5 both.
You can look at MKReverseGeocoder, however it is deprecated in iOS5 but still will serve the purpose. For confirmation you can check so called 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];
}
You can use this function for getting address from latitude, longitude. You can change according to requirement. We put this as Class method so we can directly use it as
NSString *strAddressFromLatLong = [CLassName getAddressFromLatLon:37.484848 withLongitude:74.48489];
EDIT
Please stop using above function as it has stopped working reported in comments (Not tested by me). I recommend to start using SVGeocoder
Upvotes: 23
Reputation: 1424
//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
Sorry for my bad english hope it willhelp you
Upvotes: 5