Coordinates/Region from Country Name - objective-c

How can I extract a CLRegion or CLLocationCoordinate2D or latitude/longitude points based on a correctly written country name? Would CLGeocoder work like this:
CLGeocoder *geoCode = [[CLGeocoder alloc] init];
[geoCode geocodeAddressString:#"Singapore" completionHandler:^(NSArray *placemarks, NSError *error) {
if (!error) {
CLPlacemark *place = [placemarks objectAtIndex:0];
NSLog(#"%i,%i", place.//what would i put here);
}
}];
What variable does a CLPlacemark hold that tells the address?

Never mind figured it out:
CLGeocoder *geoCode = [[CLGeocoder alloc] init];
[geoCode geocodeAddressString:#"Singapore" completionHandler:^(NSArray *placemarks, NSError *error) {
if (!error) {
CLPlacemark *place = [placemarks objectAtIndex:0];
CLLocation *location = place.location;
CLLocationCoordinate2D coord = location.coordinate;
NSLog(#"%g is latitude and %g is longtitude", coord.latitude, coord.longitude);
}
}];

Related

Can't reverse geolocate using lat/long - throws type errors

I am able to get the user latitude and longitude and display them correctly in the console log... but I can't reverse geolocate to a city name or anything with them.
What am I doing wrong?
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
CLLocation *userlatitude = [locations lastObject];
CLLocation *userlongitude = [locations objectAtIndex:locations.count-2];
CLGeocoder *ceo = [[CLGeocoder alloc]init];
CLLocation *loc = [[CLLocation alloc]initWithLatitude:userlatitude longitude:userlongitude];
[ceo reverseGeocodeLocation: loc completionHandler: ^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSString *locatedAt = [[placemark.addressDictionary valueForKey:#"FormattedAddressLines"] componentsJoinedByString:#", "];
NSLog(#"Currently located at %#",locatedAt);
}];
[locationManager stopUpdatingLocation];
}
I have also tried replacing CLLocation *userlatitude .... objectAtIndex:location.count-2]; with
CLLocationDegrees userlatitude = [[locations lastObject] doubleValue];
CLLocationDegrees userlongitude = [[locations objectAtIndex:locations.count-2] doubleValue];
but this returns an error during runtime (even though it does not show any syntax errors in the code editor).
didUpdateLocations method returns a array of CLLocation objects containing the location data. This array always contains at least one object representing the current location.
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
CLGeocoder *ceo = [[CLGeocoder alloc]init];
[ceo reverseGeocodeLocation:(CLLocation *)[locations lastObject] // pass the most recent value
completionHandler: ^(NSArray *placemarks, NSError *error) {
if (error) {
NSLog(#"reverse error: %#", error);
// handle error here
return;
}
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSString *locatedAt = [[placemark.addressDictionary valueForKey:#"FormattedAddressLines"]
componentsJoinedByString:#", "];
NSLog(#"Currently located at %#",locatedAt);
}];
}

unexpected results from geocodeAddressString

My question is, why are poiCoordinate's latitude and longitude properties coming out 0, 0 when addressTF.text has a very sensible address string, for example "1 Infinite Loop, Cupertino, CA 95014"?
//HomeViewController.m
#implementation HomeViewController
CLLocationCoordinate2D poiCoordinate;
-(void)performStringGeocode
{
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:_addressTF.text completionHandler:^(NSArray *placemarks, NSError *error)
{
if (error)
{
NSLog(#"Geocode failed with error: %#", error);
return;
}
CLPlacemark *placemark = [placemarks firstObject]; //Line A
poiCoordinate = placemark.location.coordinate; //Line B
}];
}

What is wrong with this locking scheme

for (NSString * district in allLinedStrings) {
PO1(district);
[self.mainLock lock];
CLGeocoder * geocode= [[CLGeocoder alloc]init];
[geocode geocodeAddressString:district completionHandler:^(NSArray *placemarks, NSError *error )
{
for (CLPlacemark * thePlace in placemarks)
{
[self handlePlacemark:thePlace];
}
[self.mainLock unlock];
}];
}
I want to run geocodeAddressString synchronously and I do this. Somehow I got error of deadlock. But what's wrong?
If you are using NSLock: Calling the lock method twice on the same thread will lock up your thread permanently.
for (NSString * district in allLinedStrings) {
PO1(district);
[self.mainLock lock];
CLGeocoder * geocode= [[CLGeocoder alloc]init];
[geocode geocodeAddressString:district completionHandler:^(NSArray *placemarks, NSError *error )
{
for (CLPlacemark * thePlace in placemarks)
{
[self handlePlacemark:thePlace];
}
}];
[self.mainLock unlock];
}

How to reverse geocode the continent using CLGeocoder?

Surprisingly, I wasn't able to find ANY meaningfull information in 30 minutes of search in all the right places..it's suspicious, I think I am doing something wrong.
I would add, that the solution should be without requiring third party code or webservices..
How are you using the CLGeocoder at the moment. Without seeing some code not much we can suggest ...
However, if you are trying to get information on where the user is or where a location is you can use this:
{
CLLocationManager *location = [[CLLocationManager alloc] init];
[location setDelegate:self];
[location startUpdatingLocation];
[location setDesiredAccuracy:kCLLocationAccuracyBest];
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location.location completionHandler:^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSLog(#"%# %# %# %# %# %# %# %#", placemark.country, placemark.ISOcountryCode, placemark.postalCode, placemark.administrativeArea, placemark.locality, placemark.subLocality, placemark.thoroughfare, placemark.subThoroughfare);
[geocoder release];
[location release];
}];
}
I actually wrote a category to address this caveat in the CLPlacemark class.
It currently uses the -ISOCountryCode property to map it to its correspondent continent.
https://github.com/Hecktorzr/Transcontinental

Altering values within blocks in Objective - C

I have a block of code that adds an object to an array declared outside the block with the "__block" notation (it's an ivar). However, once the block is exited, the array contains no values. I know that it isn't trying to add empty strings to the array, because my console prints the strings correctly. Any help would be appreciated. Here is my code:
addressOutputArray = [[NSMutableArray alloc] init];
for(CLLocation *location in locationOutputArray)
{
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error)
{
if(placemarks && placemarks.count > 0)
{
CLPlacemark *topResult = [placemarks objectAtIndex:0];
NSString *address = [NSString stringWithFormat:#"%# %#,%# %#", [topResult subThoroughfare],[topResult thoroughfare],[topResult locality], [topResult administrativeArea]];
[addressOutputArray addObject:address];
NSLog(#"%#",address);
}
}];
[geocoder release];
}
NSLog(#"Address output array count: %d", [addressOutputArray count]);
The final log gives me a count of zero. Any help at all would be really appreciated.
The problem is that reverseGeocodeLocation executes asynchronously, and you are not waiting for the calls to complete before logging the size of your output array. You might have better luck with something like:
for(CLLocation *location in locationOutputArray)
{
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error)
{
if(placemarks && placemarks.count > 0)
{
CLPlacemark *topResult = [placemarks objectAtIndex:0];
NSString *address = [NSString stringWithFormat:#"%# %#,%# %#", [topResult subThoroughfare],[topResult thoroughfare],[topResult locality], [topResult administrativeArea]];
[addressOutputArray addObject:address];
NSLog(#"%#",address);
NSLog(#"Address output array count is now: %d", [addressOutputArray count]);
}
}];
[geocoder release];
}
In any case, you are doing everything correctly with your block in terms of how you are setting it up and using it to modify the state of your addressOutputArray ivar. The only problem is that you were not waiting until all your blocks had finished executing before checking the result.