Using CLGeocoder to find the nearest city - iphone

So I've been looking at this for a while, and I can't seem to find a solution anywhere. I am trying to use CLGeocoder in an iOS app to find the nearest city to where the user long taps on the map. I have two main problems:
Even if the user is very zoomed out, and the user taps on say New York (which is what they intend), because of how zoomed out the map is, CLGeocoder often returns a nearby city instead of the more obvious answer of New York. I can't work out how to set the "fuzziness" of the search to overcome this issue.
In many instances the City field is null in the returned placemark object, most commonly in remote areas such as deserts or oceans. In this case, I would ideally want to find the nearest object that actually has City defined, but can't work out how to do this.

For Get all Detail of your Location by using CLGeocoder
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
[currentLocation stopUpdatingLocation];
CLLocation *myLocation = [[CLLocation alloc] initWithLatitude:latitudeValue longitude:longitudeValue];
CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
[geoCoder reverseGeocodeLocation:myLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if(!error)
{
for (CLPlacemark * placemark in placemarks)
{
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);
}
}
else
{
NSLog(#"failed getting city: %#", [error description]);
}
}];
}

Related

set a constant language to CLPlacemark instance class

i have looked every where and didn't found an answer for this one.
i'm building an iOS app that uses the location (lat + long) of the user
creating a CLPlacemark, and sends the street + country to the server and get back a respond according to this location.
now the server can get only hebrew values, and the CLPlacemark values are changes according to the operation system of the user.
can i set a const language to the CLPlacemark class instance?
i want that the CLPlacemark will return hebrew regardless from the operation system of the user
here is my code:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
geoCoder = [[CLGeocoder alloc]init];
[self.geoCoder reverseGeocodeLocation:locationManager.location completionHandler:
^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
placemark.
self.countryTextBox.text =[placemark.addressDictionary valueForKey:#"Country"];
self.citiTextBox.text =[placemark.addressDictionary valueForKey:#"City"];
self.streetTextBox.text =[placemark.addressDictionary valueForKey:#"Street"];
self.zipCodLbl.text =[placemark.addressDictionary valueForKey:#"ZIP"];
//NSLog(#"%#",placemark.addressDictionary);
NSLog(#"%#",[placemark.addressDictionary valueForKey:#"Country"]);
NSLog(#"%#",[placemark.addressDictionary valueForKey:#"City"]);
NSLog(#"%#",[placemark.addressDictionary valueForKey:#"Street"]);
NSLog(#"%#",[placemark.addressDictionary valueForKey:#"ZIP"]);
[locationManager stopUpdatingLocation];
[self.animationBar stopAnimating];
}];
}
thanks a lot.
idan.
after a hard days of searching im finally solve it.
in the view did load just add this line of code:
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:#"he"] forKey:#"AppleLanguages"];
if this will help somebody - great!
Messing with user's system preference is BAD PRACTICE!!
You should use instead:
NSLocale *yourLocal = [[NSLocale alloc] initWithLocaleIdentifier:#"de"];
[geoCoder reverseGeocodeLocation: preferredLocale:yourLocal completionHandler:
^(NSArray *placemarks, NSError *error) {
}];

Get Location information Using CLPlaceMark And CLGeocoder

I have been completed drawing the route between two places using ClLocationCoordinate2D on map in ios 6 dynamically.Can anyone please help me out in getting the location name using CLPlacemark and CLGeocoder as reverse geocoder has been deprecated in ios 6.
you can get information like bellow with its Delegate method..
UPDATE:
First Define this variable in .h file like bellow..
NSString *postcode,*locationName;
and use it in bellow method...
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
[geoCoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) {
for (CLPlacemark * placemark in placemarks) {
postcode = [placemark postalCode];
[postcode retain];
locationName = [placemark name];
[locationName retain];
NSLog(#"\n placemark %#",placemarks);
}
}];
[geoCoder release];
NSLog(#"\n Location Name ==> %# ----> GotPostCode:%#",locationName,postcode);
}
here you can also use other property of CLGeocoder like locality,location,etc...
A CLPlacemark object stores placemark data for a given latitude and longitude. Placemark data includes information such as the country, state, city, and street address associated with the specified coordinate.
Check Link

Find the current location using CLGeocoder Reverse Geocoding

I want to find the current location of user based on latitude and longitude. Prevoiusly I have done it using MKReverseGeocoder but as it is depracated in ios5 ,I going with CLGeocoder.But unable to get the current location .
- (void)viewDidLoad
{
locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
[locationManager setDistanceFilter:kCLDistanceFilterNone];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
CLLocation *currentLocation = newLocation;
locationLabelOne=newLocation.coordinate.latitude;
locationLabelTwo=newLocation.coordinate.longitude;
geocoder = [[CLGeocoder alloc] init];
[locationManager stopUpdatingLocation];
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"Found placemarks: %#, error: %#", placemarks, error);
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
NSString *get = [NSString stringWithFormat:#"%# %#\n%# %#\n%#\n%#",
placemark.subThoroughfare, placemark.thoroughfare,
placemark.postalCode, placemark.locality,
placemark.administrativeArea,
placemark.country];
} else {
NSLog(#"%#", error.debugDescription);
}
} ];
NSLog(#"%#",placemark);
}
When I NSLog placemark it is returning null.Where I m going wrong?
Possible issues:
1) locationManager:didUpdateToLocation:fromLocation is deprecated iOS 6.0 you should use locationManager:didUpdateLocations: instead.
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
{
currentLocation=[locations lastObject];
// rest code will be same
}
2) Also [locationManager stopUpdatingLocation]; sounds fishy. IMO you should not use that in CLLocationManagerDelegatemethod.
P.S.
i) For more details in Forward/Reverse geocoding you can look into Apple's sample code GeocoderDemo
ii) If you use Google API for Reverse Geocoding it will have all data available it has been for years but CLGeocoder will not have complete data like street name, pin code for countries like India. What happens is, when you do Reverse Geocoding requests, you pass co ordinates to Core Location which connects to web service in background(which developer won't come to know) and returns a user-readable address. So it may be possible this web service may not be able to return data as accurate as GOOGLE API.
I had the same problem, then with some experimentation I solved my problem…
Make sure:
-90 < latitude < 90
-180 < longitude < 180
It doesn't seem to perform a basic mod function. Hope that helps...

why the didEnterRegion called twice?

I am using location services i.e. region monitoring in my iOS app,
This is my code
//this for creating region
-(void)createRegion
{
[dictionary setValue:#"23 St, New York" forKey:#"title"];
[dictionary setValue:[NSNumber numberWithDouble:40.742878] forKey:#"latitude"];
[dictionary setValue:[NSNumber numberWithDouble:-73.992821] forKey:#"longitude"];
[dictionary setValue:[NSNumber numberWithDouble:(300.0)] forKey:#"radius"];
[regionArray addObject:[self mapDictionaryToRegion:dictionary]];
[self initializeRegionMonitoring:regionArray];
}
- (CLRegion*)mapDictionaryToRegion:(NSDictionary*)dictionary {
NSString *title = [dictionary valueForKey:#"title"];
CLLocationDegrees latitude = [[dictionary valueForKey:#"latitude"] doubleValue];
CLLocationDegrees longitude =[[dictionary valueForKey:#"longitude"] doubleValue];
CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake(latitude, longitude);
CLLocationDistance regionRadius = [[dictionary valueForKey:#"radius"] doubleValue];
return [[CLRegion alloc] initCircularRegionWithCenter:centerCoordinate
radius:regionRadius
identifier:title];
}
- (void) initializeRegionMonitoring:(NSArray*)geofences {
if(![CLLocationManager regionMonitoringAvailable]) {
// [self showAlertWithMessage:#"This app requires region monitoring features which are unavailable on this device."];
return;
}
for(CLRegion *geofence in geofences) {
[_locationManager startMonitoringForRegion:geofence];
}
}
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
NSLog(#"entered region %#",region.identifier);
}
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
NSLog(#"exited region %#",region.identifier);
}
It works fine when app is in foreground. It shows me log :"entered region.." and "exited region ..",
but when app goes to background then same logs are printed twice in just fraction of second, i.e. delegate methods called twice, that i don't need, is there any way to avoid calling 2 times?
or is am doing any mistake while creating or monitoring regions ?
please help me ..
thanks in advance ..
I believe this question is a duplicate of my own. I think there is a bug with Apple's region monitoring APIs. I have filed a radar for this issue with Apple already, but have not heard anything back as of yet.
One way I get around this is by saving the timestamp in the didEnter and didExit methods and if the methods fire within 10 seconds of the saved timestamp, just skip the method as a dupe.
If anyone is interested, I have a project on github showing this problem in action.
https://github.com/billburgess/GeofenceBug
Feel free to file another radar as that is the only way Apple will notice the issue and take action. The radar number is 12452255 - Duplicate Delegate calls for region monitoring.
Here is the open radar link with the information if you would like to dupe this radar.
http://openradar.appspot.com/radar?id=2484401

Returning a users lat lng as a string iPhone

Is there a way to return the users location as a string from a model?
I have a model thats job is to download same JSON data from a web service. When sending in my request I need to add ?lat=LAT_HERE&lng=LNG_HERE to the end of the string.
I have seen tons of examples using the map or constantly updating a label. But I cant find out how to explicitly return the lat and lng values.
Im only 2 days into iPhone dev so go easy on me :)
You need to leverage Core Location, specifically CLLocationManager. Apple doesn't provide any CL programming guide, so just look at one of the samples like LocateMe to see how to do it.
You need to use CLLocationManager like this:
- (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
{
// retrieve lat and lng in a string from newLocation.coordinate
NSString *lat = [NSString stringWithFormat:#"%d", newLocation.coordinate.latitude];
NSString *lng = [NSString stringWithFormat:#"%d", newLocation.coordinate.longitude];
}
// 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);
}