I have a list of geographical locations in Core Data (entity name is "Stops").
I want to sort them by the current location, so I can show the user which locations are nearby. I'm using an NSFetchedResultsController so that the results can be easily displayed in a UITableView.
I am using the following code to attempt this sort:
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 is just returning all of my items sorted by the key I specified ("stop_lat") rather than sorted by the user's current location.
It looks like my comparator block isn't ever getting called, because the NSLog in there never prints.
What am I missing here?
Objective-C based sort descriptors cannot be used with a fetch request.
From the "Core Data Programming Guide":
... To summarize, though, if you execute a fetch directly, you should typically not add Objective-C-based predicates or sort descriptors to the fetch request. Instead you should apply these to the results of the fetch.
A different take on this would be to have a property on your 'Stop' managedObject called meanSquared (probably an NSDecimalNumber).
When your device lat/long has moved sufficiently to alter the 'nearest Stop' data, then you update all 'Stop' objects with the meanSquared distance (i.e. (yourLat-stopLat)^2+(yourLong-stopLong)^2), then just use 'meanSquared' in your sortDescriptor.
Depending on the number of times that you update the user's position, the distance between stops and the number of stops this might be an optimal solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With