NSSortDescriptor - sort by location

I have a list of geographical locations in Core Data (the name of the object is "Stops").

I want to sort them by current location, so I can show the user which locations are nearby. I am using NSFetchedResultsController so that the results can be easily displayed in a UITableView.

I am using the following code to try this view:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"stop_lat" ascending:YES comparator:^NSComparisonResult(Stops *obj1, Stops *obj2) { CLLocation *currentLocation = locationManager.location; CLLocation *obj1Location = [[CLLocation alloc]initWithLatitude:[obj1.stop_lat doubleValue] longitude:[obj1.stop_lon doubleValue]]; CLLocation *obj2Location = [[CLLocation alloc]initWithLatitude:[obj2.stop_lat doubleValue] longitude:[obj2.stop_lon doubleValue]]; CLLocationDistance obj1Distance = [obj1Location distanceFromLocation:currentLocation]; CLLocationDistance obj2Distance = [obj2Location distanceFromLocation:currentLocation]; NSLog(@"Comparing %@ to %@.\n Obj1 Distance: %f\n Obj2 Distance: %f",obj1.stop_name, obj2.stop_name, obj1Distance, obj2Distance); if (obj1Distance > obj2Distance) { return (NSComparisonResult)NSOrderedDescending; } if (obj1Distance < obj2Distance) { return (NSComparisonResult)NSOrderedAscending; } return (NSComparisonResult)NSOrderedSame; }]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; [fetchRequest setSortDescriptors:sortDescriptors]; [fetchRequest setEntity:[NSEntityDescription entityForName:[Stops entityName] inManagedObjectContext:context]]; frcNearby = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil]; NSError *error; BOOL success = [frcNearby performFetch:&error]; if (error) NSLog(@"ERROR: %@ %@", error, [error userInfo]); 

However, my NSFetchedResultsController simply returns all my items sorted by the key I specified ("stop_lat"), and not sorted by the user's current location.

It seems like my comparator block is never called because NSLog never prints there.

What am I missing here?

+4
source share
4 answers

Objective-C sort descriptors cannot be used with a select query.

In the "Master Data Programming Guide":

... To summarize, however, if you are fetching directly, you should usually not add Objective-C-based predicates or sort query request descriptors. Instead, you should apply them to the sample results.

+6
source

Another thing is to have a property in the "Stop" managed object called meanSquared (possibly NSDecimalNumber).

When your lat / long device has moved enough to change the “nearest stop” data, you update all stop objects with an “average” distance (i.e. (yourLat-stopLat) ^ 2 + (yourLong-stopLong) ^ 2) then just use "meanSquared" in your sortDescriptor.

Depending on the number of times you update the user's position, the distance between stops and the number of stops this may be the best solution.

+3
source

You cannot sort by lat / Lon anyway, you will need to calculate the distance for each point and sort by it. Or select a range of lat / Lon values ​​next to the user, select this subset, calculate the distance for them and show. the range will be similar to user lat +/- 0.1 degrees, etc. for sampling.

+1
source

I would recommend the following approach:

See the Geographic Address Predicate section in http://www.objc.io/issue-4/core-data-fetch-requests.html

It gets approximate results using a predicate, and then sorts them exactly in memory.

+1
source

All Articles