CLGeocoder not returning neighborhood name when I reversegeocode - core-location

I am currently working on an app that will use the data returned by reversegeocode. Right now I can successfully receive the following values for a location: address, city, state, zip code, and country. In addition to the values that I am able to get, I would also like to obtain the name of the neighborhood for the locations that I reversegeocode. My code is as follows:
CLLocationManager *location = [[CLLocation alloc] init];
[location setDelegate:self];
location.desiredAccuracy=kCLLocationAccuracyBest;
location.distanceFilter=kCLDistanceFilterNone;
[location startMonitoringSignificantLocationChanges];
CLGeocoder *geolocation = [[CLGeocoder alloc] init];
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(#"Update method is definitely being called!");
NSLog(#"Your current location is : %#", [locations lastObject]);
[geolocation reverseGeocodeLocation:[locations lastObject] completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"Reverse geocode complete: %#", placemarks);
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSLog(#"The locality area is: %#", placemark.locality);
}];
}
I expected placemark.locality to return the neighborhood but it returns the city instead.
Any help would be greatly appreciated,
Dave

After reading the documentation Apple has for the CLPlacemark class, I noticed that there were a few fields that I was unaware of.
Inclusive in these fields is exactly what I was trying acquire, the subLocality, which seems to be Apple documentation for neighborhood. If I had just read the documentation instead of assuming the object returned from [placemarks objectAtIndex:0], when stored in CLPlacemark *placemark, would have no more data than what is shown when NSLog(#"%#", [placemarks objectAtIndex:0]) is called, I would have figured this out much sooner. Oh well. The code I used to access the neighborhood is:
[placemark subLocality];

Related

How to sort Core Data results based on an attribute of related object collection?

Setup: I have a collection of parent objects, call them ObjectA. Each ObjectA has a one-to-many relation to ObjectB. So, one ObjectA may contain 0..n ObjectB-s, and each ObjectB has a specific ObjectA as its parent.
Now, I would like to do a Core Data fetch of ObjectA-s, where they are sorted by their latest ObjectB. Is it possible to create a sort descriptor for that?
There is a related question that describes exactly the same situation. The answer suggests denormalizing the attribute from ObjectB into ObjectA. This would be OK if there really is no way to do this with one fetch request.
The related question also mentions:
Actually, I just had an idea! Maybe I can sort Conversations by messages.#max.sortedDate…
I tried. It doesn’t seem to be possible. I get this error:
2012-10-05 17:51:42.813 xxx[6398:c07] *** Terminating app due to uncaught
exception 'NSInvalidArgumentException', reason: 'Keypath containing
KVC aggregate where there shouldn't be one; failed to handle
ObjectB.#max.creationTime'
Is denormalizing the attribute into ObjectA the only/best solution?
You could add an attribute in ObjectB which is the time stamp of the add date, then in the fetch request you can do something like this:
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"objectB.addTime" ascending:YES];
...
fetchRequest.sortDescriptors = #[descriptor];
I know this question is a bit old but what I did was get all ObjectBs, iterate over the results and pull out the ObjectB property and add it to a new array.
NSFetchRequest *fetchRequest = [NSFetchRequest new];
[fetchRequest setEntity:self.entityDescForObjectB];
// sort
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"date" ascending:YES];
[fetchRequest setSortDescriptors:#[sortDescriptor]];
NSError *error = nil;
NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
NSLog(#"Error fetching objects: %#", error.localizedDescription);
return;
}
// pull out all the ObjectA objects
NSMutableArray *tmp = [#[] mutableCopy];
for (ObjectB *obj in fetchedObjects) {
if ([tmp containsObject:obj.objectA]) {
continue;
}
[tmp addObject:obj.objectA];
}
This works because CoreData is an object graph so you can work backwards. The loop at the end basically checks to see if the tmp array already has a specific ObjectA instance and if not adds it to the array.
It's important that you sort the ObjectBs otherwise this exercise is pointless.

CoreData autosaving and not loading all data after autosave

I have an NSPersistentDocument subclass using NSManagedObject subclasses for my data.
When a new document is opened, I do some initializing of data structures (trivial amount of populating fields). What I've noticed is that the Untitled document gets autosaved, and when the application re-opens, that document gets loaded. If the application quits, the user doesn't (by default) get prompted with the save dialog. If the window closes, the user does.
First question:
I want to call up the save dialog when the user quits the application. I don't want this Untitled document hanging around (under normal circumstances). I either want it saved or trashed.
I attempted to fill out:
- (void)applicationWillTerminate:(NSNotification *)aNotification
In order to trigger the document to be saved. Calling save: on the context at this point gives an error. From what I can tell, this is because the user hasn't yet saved the file on their own. In addition, calling [self close]; or [[self windowForSheet] close]; close the window without saving.
How can I force the save dialog to come up? How can I trash the untitled document?
Second question (no, I can't count):
Since when the application starts, there may or may not be an Untitled document to deal with, I'm trying to keep track of the state in another model. I've already found that the initial data (to which I referred earlier) is present when the Untitled document came up. My other model has some metadata, including a success flag/state for the populated data. Once the populated data is all in place and correct, the state indicates as such. Unfortunately, while my populated data is being loaded when the app starts with a pre-existing Untitled document, the metadata class is not.
Please excuse the roughness of the code, at this point, I'm mucking it up until I can see that it's working how I want before I polish it back off:
- (bool) createGameState {
NSEntityDescription* description = [NSEntityDescription entityForName:[GameState name] inManagedObjectContext:[self managedObjectContext]];
NSFetchRequest* req = [[NSFetchRequest alloc] init];
[req setEntity:description];
NSError *error = nil;
NSArray *array = [[self managedObjectContext] executeFetchRequest:req error:&error];
[req release];
req = nil;
GameState* result = nil;
if (array) {
NSUInteger count = [array count];
if (!count) {
// Create the new GameState.
DebugLog(#"Creating GameState");
result = [NSEntityDescription insertNewObjectForEntityForName:[GameState name] inManagedObjectContext:[self managedObjectContext]];
[result setIsLoaded:[NSNumber numberWithBool:NO]];
} else {
if (count > 1) {
NSLog(#"WARNING: Potentially Corrupt Game State. found: %lu", count);
}
result = [array objectAtIndex:0];
if ([result isLoaded]) {
[self variantLoaded];
} else {
// In this case, we have an aborted set-up. Since the game isn't
// playable, just refuse to create the GameState. This will
// force the user to create a new game.
return NO;
}
}
} else {
DebugLog(#"error: %#", error);
}
[game setState:result];
return result;
}
Note that array is always present, and count is always zero. No, I'm not explicitly calling save: anywhere. I'm relying on the standard auto-save, or the user performing a save.
EDIT:
I installed the Core Data Editor app. It turns out the issue isn't on saving the data, but on loading it. (Note: Due to another issue, the app saves as binary when instructed to save as XML, which causes much head banging.)
I've broken it down to the simplest code, which should pick up all objects of type GameState in an array. It retrieves none, despite there clearly being objects of the appropriate type in the saved file:
NSManagedObjectContext* moc = [self managedObjectContext];
NSEntityDescription* entity = [NSEntityDescription entityForName:#"GameState" inManagedObjectContext:moc];
NSFetchRequest* req = [[NSFetchRequest alloc] init];
[req setEntity:entity];
NSError *error = nil;
NSArray *array = [moc executeFetchRequest:req error:&error];
Array is not null, but [array count] is 0.
At this point, I'm guessing it's something simple that I'm overlooking.
Second EDIT:
I added -com.apple.CoreData.SQLDebug 5 and saved as SQLite. The call to executeFetchRequest does not generate any debug logs. I do see the INSERT INTO ZGAMESTATE entry show up in the logs. It seems that executeFetchRequest is not getting passed to the backend.
Third EDIT (this one burns):
I created a new xcode project, using core data (as I had with the other). I copied just this one function (stubbing where necessary) and plopped a call to it in windowControllerDidLoadNib. In this new project, the code above works.
Found the problem.
I errantly was loading objects in Document's - (id) init call. Moved to windowControllerDidLoadNib (which is what I did in the test version) and it worked fine.

Count entity in Core Data with a specific Value

I have an Entity with some Attribute. I have my tabes already populates(SQLite table)
In one Attribute (i'll call Attribute1) i have a bool value, changing during use of my app.
How can i return the count of my Entities with Attribute1 value YES?
I've already read "Core data Tutorial" and "Predicate Programing Guide" but i don't understand how to proceed..
NSPredicate *predicate= [NSPredicate predicateWithFormat:#"Attribute1 == %#",[NSNumber numberWithBool:YES]];
I've tried with this, and then? it seems not working..
The best bet is to use the countForFetchRequest method. Set up your predicate and fetch request, but instead of doing the actual fetch, execute countForFetchRequest as follows:
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
NSPredicate *predicate =
[NSPredicate predicateWithFormat:#"Attribute1 == %#",
[NSNumber numberWithBool:YES]];
[request setPredicate:predicate];
NSUInteger count = [myManagedObjectContext countForFetchRequest:request error:nil];
You can find more info in the Apple API Docs:
countForFetchRequest:error:
Returns the number of objects a given fetch request would have returned if it had been passed to executeFetchRequest:error:.
(NSUInteger)countForFetchRequest:(NSFetchRequest )request error:(NSError *)error
Parameters
request
A fetch request that specifies the search criteria for the fetch.
error
If there is a problem executing the fetch, upon return contains an instance of NSError that describes the problem.
Return Value
The number of objects a given fetch request would have returned if it had been passed to executeFetchRequest:error:, or NSNotFound if an error occurs.
Availability
Available in iOS 3.0 and later.
Declared In
NSManagedObjectContext.h

Setting up basic relationship with Fetch Requests

I am wanting to set up a basic relationship with two entities in Core Data, but the relationship is either not saving, or is not working properly and I'm not sure why.
The two entities are Character and Avatar, its a one-to-one relationship. A character can have 1 avatar. Technically, it should be a "one avatar can be owned by many characters", but I'll deal with that later.
I want to add characters and assign them an avatar.
There are already 10 avatars in Core Data and 1 character, both of which I've verified via the Terminal and SQLite.
The problem is, I'm having troubling "finding an avatar by a name and then saving the relationship to a character".
So far,
I set up a fetch request called: "frqAvatarWithName" where the Predicate has the following structure:
[quote]
name == $AVATAR_NAME
[/quote]
This is so: I can find an avatar with a certain name; and then I can create a relationship with a character.
Issue 1: It gets to execute the query but then never displays how many records there are.
I get a EXC_BAD_ACCESS error in debug mode and I have traced it back to the fetch request template handling -- so, this must be in error or I have done it wrong.
Issue 2: I am not sure if I am even setting up this "basic" relationship up properly.
[code]
// This code is meant to find an avatar with a certain name and then save the relationship
// between a character and said avatar.
// This is my app delegate file for the moment
// All the files are present, and I have deleted/recreated the app various times
-(void)characterMaker
{
NSLog(#"Inside characterMaker...");
NSError *error = nil;
NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObjectModel *model = [self managedObjectModel];
// Find an avatar with a specific name
NSString *nameToFind = #"avt_player_1";
// Use a Fetch request template
NSDictionary *subs = [NSDictionary dictionaryWithObjectsAndKeys:nameToFind, #"AVATAR_NAME", nil];
NSFetchRequest *fetchRequest = [model fetchRequestFromTemplateWithName:#"frqAvatarWithName"
substitutionVariables:subs];
// Set the entity to use
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Avatar"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
// Execute the query (it never even reaches this point)
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
// Handle the error
NSLog(#"Error -- %#", [error localizedDescription]);
abort();
}
NSLog(#"Found %# records", [fetchedObjects count]);
// Print out avatar names
for (Avatar *a in fetchedObjects)
{
NSLog(#"Name = %#", [a valueForKey:#"name"]);
}
// This is where I would use `a` and store it in a character entity, and thus create the relationship
[/code]
I gave up on this and did the whole project with the FMDatabase project and SQLite; I've been able to resolve the problem this way.
Thread closed.

Search on Core data backed UITable issue?

Not sure if this is the right place (I am sure someone will let me know if it is not) I have a iPhone application that has a UITableview that is backed by core data. I want to perform a reducing search so that only the items starting with the characters entered into the search bar are shown. This is normally done with the delegate - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText no problem. I am a little confused as I am new to Core Data how to do this. One of the big problems as I see it is going to be updating the interface to let it know what to present. I assume an alternative NSFetchedResultsController needs to be sent to the UITableView is that correct?
So here are my issues:
1) I assume I need to create a NSFetchedResultsController with only the correct items in it then tell the UITableView to use this as the dataSource and reload the table?
2) is there a better way than executing a full sorted fetch and removing those objects that do not conform. ie is there a way of doing a select where type fetch?
Thanks in advance and sorry if this is a dumb question.
Regards
Damien
Yes, you will need a new NSFetchedResultsController.
You should use a NSPredicate in your new NSFetchRequest to filter by your search text.
For example, if your managed objects have a field "name" that should be filtered:
NSPredicate *pred = [NSPredicate predicateWithFormat:#"%K beginswith[c] %#", #"name", searchText];
[fetchRequest setPredicate:pred];
I used a slightly different solution: instead of relying on a different NSFetchedResultsController, I created a NSMutableArray (filteredListContent) in my table view controller, used to store the temporary data, as inspired by Apple sample code and Mugunth Kumar's tutorial.
In tableView:cellForRowAtIndexPath:, returning the appropriate data-source array:
if(receivedTableView == self.searchDisplayController.searchResultsTableView){
Objects* object = [self.filteredListContent objectAtIndex:indexPath.row];
cell.textLabel.text = object.name;
} else {
Objects* object = [self.unfilteredListContent objectAtIndex:indexPath.row];
cell.textLabel.text = object.name;
}
As in Apple's sample code, add pretty much the same method in other methods, such as
- (NSInteger)tableView:(UITableView *)receivedTableView numberOfRowsInSection:(NSInteger)section {
if(receivedTableView == self.searchDisplayController.searchResultsTableView){
return [self.filteredListContent count];
}
return [self.unfilteredListContent count];
}
As well as in tableView:didSelectRowAtIndexPath:...
Then conformed to UISearchDisplayDelegate protocol and added the following methods:
- (void)filterContentForSearchText:(NSString*)searchText
{
if (!self.filteredListContent) {
self.filteredListContent = self.filteredListContent = [[NSMutableArray alloc] init];
}
[self.filteredListContent removeAllObjects];
for (Objects *object in [self.coreDataStuffVariable.fetchedResultsController fetchedObjects])
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:
#"(SELF contains[cd] %#)", searchText];
NSString * elementTitle = [NSString stringWithFormat:#"%#", object.name];
[elementTitle compare:searchText options:NSCaseInsensitiveSearch];
if([predicate evaluateWithObject:elementTitle])
{
[self.filteredListContent addObject:password];
}
}
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString{
[self filterContentForSearchText:searchString];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
Pretty simple. I guess it can end up badly if the core data objects are reloaded during a search, but well... if you can sleep knowing that then it may be a good solution!

Resources