How can I get all the values (country, CITY(important) and thoroughfare) and from CLGeocoder only in english and ignore the language of the device?
My code:
-(void)updateLocations
{
// Create a location manager
locationManager = [[CLLocationManager alloc] init];
// Set a delegate to receive location callbacks
locationManager.delegate = self;
// Start the location manager
[locationManager startUpdatingLocation];
// [self.locationManager requestWhenInUseAuthorization];
[locationManager requestAlwaysAuthorization];
}
-(void)updateLocationManager : (CLLocationManager *)manager
{
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:locationManager.location completionHandler:^(NSArray *placemarks, NSError *error)
{
if(placemarks && placemarks.count > 0)
{
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSString *country = placemark.country;
// Getting the City
NSString *city = placemark.addressDictionary[#"City"];
NSString *thoroughfare = [placemark thoroughfare];
}
else
{
NSLog(#"Geocode failed with error: %#", error);
return;
}
}];
}
Try changing the NSUserDefaults value for AppleLanguages key before querying for the location
NSArray *currentLanguageArray = [[NSUserDefaults standardUserDefaults] objectForKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:#"en", nil] forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
//get the location
[[NSUserDefaults standardUserDefaults] setObject:currentLanguageArray forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
It is working for me, but you have to add the code like this:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
NSLog(#"lon - %#", [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude]);
NSLog(#"lat - %#", [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude]);
}
// Reverse Geocoding
NSLog(#"Resolving the Address");
NSArray *currentLanguageArray = [[NSUserDefaults standardUserDefaults] objectForKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:#"en_US", nil] forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
[_geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"Found placemarks: %#, error: %#", placemarks, error);
if (error == nil && [placemarks count] > 0) {
_placemark = [placemarks lastObject];
//addressLabel.text = [NSString stringWithFormat:#"%# %#\n%# %#\n%#\n%#",
// placemark.subThoroughfare, placemark.thoroughfare,
// placemark.postalCode, placemark.locality,
// placemark.administrativeArea,
// placemark.country];
NSLog(#"%# - %#", _placemark.locality, _placemark.country);
} else {
NSLog(#"%#", error.debugDescription);
}
[[NSUserDefaults standardUserDefaults] setObject:currentLanguageArray forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
} ];}
In the sample code I am using this variables:
#property(nonatomic, retain) IBOutlet MKMapView *mapView;
#property(nonatomic, retain) CLLocationManager *locationManager;
#property(nonatomic, retain) CLGeocoder *geocoder;
#property(nonatomic, retain) CLPlacemark *placemark;
This sample code is giving the city name and the Country in English, I have not tested the city name if it is shown in english properly, but it is probably fine.
Hope it helps!!
Try to change language and region on your device. It's works correct for me. I hope this will help
Related
I'm trying to get the postal code when my map region has changed by using CLGeocoder:
CLLocation *location = [[CLLocation alloc] initWithLatitude:13.184098 longitude:77.725978];
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
CLLocation *location=[[CLLocation alloc] initWithLatitude:13.184098 longitude:77.725978];
[self.geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error)
{
if (!(error))
{
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSLog(#"placemark %#",placemark);
NSString *Zipcode = [[NSString alloc]initWithString:placemark.postalCode];
NSLog(#"%#",Zipcode);
}
else
{
NSLog(#"Geocode failed with error %#", error); // Error handling must required
}
}];
}
i am getting response like this
{ Country = India; CountryCode = IN; FormattedAddressLines = ( Amarwara, "Madhya Pradesh", India ); Name = Amarwara; State = "Madhya Pradesh"; SubAdministrativeArea = Chhindwara; SubLocality = Amarwara; }
I'm able to get the postal code for the first time. When the region changes, I try to reverse geocode the postal code. I even tried setting the location explicitly (line 1) and it's still returning null postal code. Can any one help this strange bug?
Try this
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
CLLocation *newLocation = [[CLLocation alloc]initWithLatitude:21.1700
longitude:72.8300];
[geocoder reverseGeocodeLocation:newLocation
completionHandler:^(NSArray *placemarks, NSError *error) {
if (error) {
NSLog(#"Geocode failed with error: %#", error);
return;
}
if (placemarks && placemarks.count > 0)
{
CLPlacemark *placemark = placemarks[0];
NSDictionary *addressDictionary =
placemark.addressDictionary;
NSLog(#"%# ", addressDictionary);
NSString *address = [addressDictionary
objectForKey:(NSString *)kABPersonAddressStreetKey];
NSString *city = [addressDictionary
objectForKey:(NSString *)kABPersonAddressCityKey];
NSString *state = [addressDictionary
objectForKey:(NSString *)kABPersonAddressStateKey];
NSString *zip = [addressDictionary
objectForKey:(NSString *)kABPersonAddressZIPKey];
NSLog(#"%# %# %# %#", address,city, state, zip);
}
}];
I am building my application on objective c using mapkit and CLLCOATION framework. I want to get the direction between the current location and fixed location STORED IN .plist but it doesn't worked with me
I got this error error Error Domain=MKErrorDomain Code=5 "Directions Not Available" {NSLocalizedFailureReason=A route to the destination from its nearest road cannot be determined, MKErrorGEOError=-403, MKDirectionsErrorCode=7, NSLocalizedDescription=Directions Not Available} with handling diretion. to note I used locations in supported apple locations in europe.
I used the following code
- (void) getDirection {
MKDirectionsRequest *request =[[MKDirectionsRequest alloc]init];
request.source= [MKMapItem mapItemForCurrentLocation];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
CLLocationDegrees longitude = [defaults doubleForKey:#"longitude"];
CLLocationDegrees latitude = [defaults doubleForKey:#"latitude"];
MKPlacemark *destinationPlaceMark = [[MKPlacemark alloc] initWithCoordinate:CLLocationCoordinate2DMake(latitude,longitude) addressDictionary:nil];
MKMapItem *destination = [[MKMapItem alloc] initWithPlacemark:destinationPlaceMark];
request.destination =destination;
request.transportType=MKDirectionsTransportTypeAny;
request.requestsAlternateRoutes = NO;
MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
[directions calculateDirectionsWithCompletionHandler:
^(MKDirectionsResponse *response, NSError *error) {
if (error) {
NSLog(#"error %# with handling diretion", error);
} else {
[self showRoute:response];
}
}];
}
- (void)showRoute:(MKDirectionsResponse *)response
{
for (MKRoute *route in response.routes)
{ NSLog(#"new route");
[self.map addOverlay:route.polyline level:MKOverlayLevelAboveRoads];
for(MKRouteStep *step in route.steps)
{
NSLog(#"%#",step.instructions);
[self.directionarray addObject:step.instructions];
}
NSLog(#"saving direction...");
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:self.directionarray forKey:#"Direction"];
[defaults synchronize];
}
}
I have an app that gives a user there current location via reverse geocode using the following.
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
NSLog(#"Location: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
latitude = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
longitude = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
//end hear for just long lat
}
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if (error == nil && [placemarks count] >0) {
placemark = [placemarks lastObject];
self.addressLable.text = [NSString stringWithFormat:#"%# %#\n%# %#\n%#\n%#",
placemark.subThoroughfare, placemark.thoroughfare,
placemark.postalCode, placemark.locality,
placemark.administrativeArea,
placemark.country];
streetandNo = [NSString stringWithFormat:#"%# %#", placemark.subThoroughfare,placemark.thoroughfare];
suberb = [NSString stringWithFormat:#"%#", placemark.locality];
}else {
NSLog(#"%#", error.debugDescription);
}
}];
[self performSelector:#selector(stopupdate) withObject:nil afterDelay:2.0];
}
This works perfectly. What i want to know is there a way to give location coordinates that are previously saved and then basically run the same process? I have looked at the apple docs and every thing i can find refers to using current location. I am hopping that there is a way to create a location under CLLocation and set my own long and Latt but i can't seem to find a reference that leads me in the right direction.
float longitude = Your saved longitude;
float latitude = Your saved latitude;
CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
Now use location in your code instead of currentLocation
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
if (error == nil && [placemarks count] >0) {
placemark = [placemarks lastObject];
self.addressLable.text = [NSString stringWithFormat:#"%# %#\n%# %#\n%#\n%#",
placemark.subThoroughfare, placemark.thoroughfare,
placemark.postalCode, placemark.locality,
placemark.administrativeArea,
placemark.country];
streetandNo = [NSString stringWithFormat:#"%# %#", placemark.subThoroughfare,placemark.thoroughfare];
suberb = [NSString stringWithFormat:#"%#", placemark.locality];
}else {
NSLog(#"%#", error.debugDescription);
}
}];
May be it will work for you.
-(IBAction)SendTextTapped:(id)sender{
if ([MFMessageComposeViewController canSendText]) {
MFMessageComposeViewController* messageController = [[MFMessageComposeViewController alloc] init];
messageController.messageComposeDelegate = self;
__block NSString *fullA = [[NSString alloc] init];
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
CLLocation *newerLocation = [[CLLocation alloc]initWithLatitude:21.1700
longitude:72.8300];
[geocoder reverseGeocodeLocation:newerLocation
completionHandler:^(NSArray *placemarks, NSError *error) {
if (error) {
NSLog(#"Geocode failed with error: %#", error);
return;
}
if (placemarks && placemarks.count > 0)
{
CLPlacemark *placemark = placemarks[0];
NSDictionary *addressDictionary =
placemark.addressDictionary;
NSLog(#"%# ", addressDictionary);
NSString *address = [addressDictionary
objectForKey:(NSString *)kABPersonAddressStreetKey];
NSString *city = [addressDictionary
objectForKey:(NSString *)kABPersonAddressCityKey];
NSString *state = [addressDictionary
objectForKey:(NSString *)kABPersonAddressStateKey];
NSString *zip = [addressDictionary
objectForKey:(NSString *)kABPersonAddressZIPKey];
NSLog(#"%# %# %# %#", address,city, state, zip);
//NSLog(fullA);
fullA=(#"%# %# %# %#", address,city, state, zip);
}
}];
[messageController setBody:fullA];
[self presentModalViewController:messageController animated:YES];
}
else {
NSLog(#"%#" , #"Sorry, you need to setup mail first!");
}
}
I have attempted using __block, or everything I could find in online tutorials.
This does print out the full address in NSLog. However, no matter what I have tried this does not show up for [messageController setBody:(#"%# %# %# %#",city, state, address, zip)];
and using (setBody:#"Hello") works just fine...
I'm sure there is something small that I can do to fix this, but everything I have tried has failed. Any ideas would be great!
You can't do what you are doing the way you are doing it. The call to reverseGeocodeLocation is asynchronous. You end up presenting the message controller long before you get back the address information. This is why the body is always empty.
You need to modify the code to create and display the message composer from within the completion handler (but you must dispatch the code on the main queue).
- (IBAction)SendTextTapped:(id)sender{
if ([MFMessageComposeViewController canSendText]) {
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
CLLocation *newerLocation = [[CLLocation alloc]initWithLatitude:21.1700 longitude:72.8300];
[geocoder reverseGeocodeLocation:newerLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if (error) {
NSLog(#"Geocode failed with error: %#", error);
return;
}
NSString *body = #"";
if (placemarks && placemarks.count > 0) {
CLPlacemark *placemark = placemarks[0];
NSDictionary *addressDictionary =
placemark.addressDictionary;
NSLog(#"%# ", addressDictionary);
NSString *address = [addressDictionary
objectForKey:(NSString *)kABPersonAddressStreetKey];
NSString *city = [addressDictionary
objectForKey:(NSString *)kABPersonAddressCityKey];
NSString *state = [addressDictionary
objectForKey:(NSString *)kABPersonAddressStateKey];
NSString *zip = [addressDictionary
objectForKey:(NSString *)kABPersonAddressZIPKey];
NSLog(#"%# %# %# %#", address,city, state, zip);
//NSLog(fullA);
body = [NSString stringWithFormat:#"%# %# %# %#", address,city, state, zip];
}
dispatch_async(dispatch_get_main_queue(), ^{
MFMessageComposeViewController* messageController = [[MFMessageComposeViewController alloc] init];
messageController.messageComposeDelegate = self;
[messageController setBody:body];
[self presentModalViewController:messageController animated:YES];
});
}];
} else {
NSLog(#"%#" , #"Sorry, you need to setup mail first!");
}
}
Use stringWithFormat in order to set body with different objects, something like this
[messageController setBody:[NSString stringWithFormat:#"%# %# %# %#",city, state, address, zip];
I saw from another question here : Determine iPhone user's country that it is possible to get the current country the user of the iPhone is in.
And that is quite convenient for many uses. However, would it be possible to go even deeper and infer from iOS (if it has the information) which state or city the user is in as well?
I suppose reverse geocoding services would be the next step if things weren't possible.. Are there even such things as a reverse geocoding service you can hire for your app though?
MKReverseGeocoder is deprecated in iOS 5, now it's CLGeocoder
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
[self.locationManager stopUpdatingLocation];
CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
[geoCoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) {
for (CLPlacemark * placemark in placemarks) {
.... = [placemark locality];
}
}];
}
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
CLLocation *newLocation = [[CLLocation alloc]initWithLatitude:21.1700
longitude:72.8300];
[geocoder reverseGeocodeLocation:newLocation
completionHandler:^(NSArray *placemarks, NSError *error) {
if (error) {
NSLog(#"Geocode failed with error: %#", error);
return;
}
if (placemarks && placemarks.count > 0)
{
CLPlacemark *placemark = placemarks[0];
NSDictionary *addressDictionary =
placemark.addressDictionary;
NSLog(#"%# ", addressDictionary);
NSString *address = [addressDictionary
objectForKey:(NSString *)kABPersonAddressStreetKey];
NSString *city = [addressDictionary
objectForKey:(NSString *)kABPersonAddressCityKey];
NSString *state = [addressDictionary
objectForKey:(NSString *)kABPersonAddressStateKey];
NSString *zip = [addressDictionary
objectForKey:(NSString *)kABPersonAddressZIPKey];
NSLog(#"%# %# %# %#", address,city, state, zip);
}
}];
Result
{
City = Surat;
Country = India;
CountryCode = IN;
FormattedAddressLines = (
Surat,
Gujarat,
India
);
Name = Surat;
State = Gujarat;
}
2012-12-20 21:33:26.284 CurAddress[4110:11603] (null) Surat Gujarat (null)
I would start with the CLReverseGeocoder class.
This stackoverflow question gets the current city and can probably be adapted for your use.
Following codes can be easy to retrieve full-details.
[geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if(placemarks.count){
placeNameLabel.text = [placemarks[0] name];
streetNumberLabel.text = [placemarks[0] subThoroughfare];
streetLabel.text = [placemarks[0] thoroughfare];
neighborhoodLabel.text = [placemarks[0] subLocality];
cityLabel.text = [placemarks[0] locality];
countyLabel.text = [placemarks[0] subAdministrativeArea];
stateLabel.text = [placemarks[0] administrativeArea]; //or province
zipCodeLabel.text = [placemarks[0] postalCode];
countryLabel.text = [placemarks[0] country];
countryCodeLabel.text = [placemarks[0] ISOcountryCode];
inlandWaterLabel.text = [placemarks[0] inlandWater];
oceanLabel.text = [placemarks[0] ocean];
areasOfInterestLabel.text = [placemarks[0] areasOfInterest[0]];
}
}];