How to reverse geocode the continent using CLGeocoder? - objective-c

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

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

CLGeocoder Multiple Addresses?

I need to geocode two different addresses but I need to have the results inside the same scope/method. How can I direct the same variables location1 and location2 inside the same block.
Here is my current code...
- (IBAction)calculateDistance {
[textFieldDestination resignFirstResponder];
NSString *origin = [textFieldOrigin text];
if (origin) {
CLGeocoder *geoCode = [[CLGeocoder alloc] init];
[geoCode geocodeAddressString:origin completionHandler: ^(NSArray *placemarks, NSError *error) {
if (!error) {
CLPlacemark *place = [placemarks objectAtIndex:0];
CLLocation *location = place.location;
CLLocation *location1 = [[CLLocation alloc] initWithLatitude:location.coordinate.latitude longitude:location.coordinate.longitude];
} else {
NSString *string = [NSString stringWithFormat:#"%# - also make sure you have inputted a valid city", [error localizedDescription]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:string delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
}];
}
NSString *destination = [textFieldDestination text];
if (destination) {
CLGeocoder *geoCode2 = [[CLGeocoder alloc] init];
[geoCode2 geocodeAddressString:destination completionHandler:^(NSArray *placemarks, NSError *error) {
if (!error) {
CLPlacemark *place = [placemarks objectAtIndex:0];
CLLocation *location = place.location;
CLLocation *location2 = [[CLLocation alloc] initWithLatitude:location.coordinate.latitude longitude:location.coordinate.longitude];
} else {
NSString *string = [NSString stringWithFormat:#"%# - also make sure you have inputted a valid city", [error localizedDescription]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:string delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
}];
}
CLLocationDistance distanceM = [location1 distanceFromLocation:location2]; // obviously error so you can see that I need location1 and location2 in the same block.... but how!?
[metreDistance setText:[NSString stringWithFormat:#"%f", distanceM]];
}
I found out how to accomplish this. For each geocoding block, I directed to a method that had specific parameters. Pretty simple, just needed to use logic!

Coordinates/Region from Country Name

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

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.

core data database is empty test

How can I test if the core data database is empty?
I tried:
NSIndexPath *path1 = [NSIndexPath indexPathForRow:0 inSection:0];
NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:path1];
if([[managedObject valueForKey:#"date"] description]!=nil){SOMEFUNCTION}else{SOMEFUNCTION}
Thanks
you have to create a fetchrequest for each entity you use in core data. if the fetchrequest returns without results you don't have objects of this entity stored in your core data.
- (BOOL)coreDataHasEntriesForEntityName:(NSString *)entityName {
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
[request setFetchLimit:1];
NSError *error = nil;
NSArray *results = [self.managedObjectContext executeFetchRequest:request error:&error];
if (!results) {
LogError(#"Fetch error: %#", error);
abort();
}
if ([results count] == 0) {
return NO;
}
return YES;
}
not perfect I admit but it works
my code:
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:0];
int fufu = [sectionInfo numberOfObjects];
if(fufu!=0){DATABASE IS NOT EMPTY}else{DATABASE IS EMPTY}
if someone know something more efective pls post it
I have these two methods implemented in my appDelegate:
- (NSString *)applicationDocumentsDirectory
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (persistentStoreCoordinator != nil)
return persistentStoreCoordinator;
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"YourApp.sqlite"]];
NSLog(#"storeURL: %#", storeUrl);
NSError *error;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
NSDictionary * options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error])
{
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be
useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
Typical reasons for an error here include:
* The persistent store is not accessible
* The schema for the persistent store is incompatible with current managed object model
Check the error message to determine what the actual problem was.
*/
}// if
return persistentStoreCoordinator;
}
The storeUrl prints the path to the sqlite database.
If you open this path with a sqlite manager, you're able to see the content of your sql database. I use this SQLite Manager to analyze sqlite databases: SQLite Manager
(You can only use this method on the simulator)