I'm working on the app that uses CoreData. There is location entity that holds latitude and longitude values. I'd like to fetch those entities sorted by distance to the user's location. I tried to set sort descriptor to distance formula sqrt ((x1 - x2)^2 + (y1 - y2)^2) but it fails with exception "... keypath ... not found in entity".
NSString *distanceFormula = [NSString stringWithFormat:@"sqrt(((latitude - %f) * (latitude - %f)) + ((longitude - %f) * (longitude - %f)))",
location.coordinate.开发者_如何学Golatitude,
location.coordinate.latitude,
location.coordinate.longitude,
location.coordinate.longitude];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:distanceFormula ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
NSError *error;
NSArray *result = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
I'd like to fetch already sorted objects rather then fetch them all and then sort in the code.
Any tips appreciated.
NSSortDescriptor
should be initialised with a key string for a property of the object, not a query string. It means you should implement your distance formula as a method of your object.
After doing so, it doesn't really matter if you sort before or after fetching:
NSArray *result = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
result = [result sortedArrayUsingSelector:@"compareDistance"];
Another point. Your distance formula doesn't work correctly, as lat. and long. don't have the same scale, unless you're on the equator. Use this:
double latDiff = lat1-lat2;
double longDiff = (long1-long2)*cos(lat1); //cos() assumes lat1 is in radians
double distance = sqrt(latDiff*latDiff+longDiff*longDiff);
If the distance is more than a few hundred kilometers, you need Spherical cosines law:
// assuming angles in radian,
double separation = acos( sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(long1-long2) );
double distance = separation*earthRadius;
精彩评论