How to get managed objects sorted by computed value

I am working on an application using CoreData. There is a location object that contains latitude and longitude values. I would like to get these objects sorted by distance to the user's location. I tried to set the sort descriptor to the sqrt ((x1 - x2) ^ 2 + (y1 - y2) ^ 2) distance formula, but with an error this exception is "... keypath ... not found in entity".

NSString *distanceFormula = [NSString stringWithFormat:@"sqrt(((latitude - %f) * (latitude - %f)) + ((longitude - %f) * (longitude - %f)))", location.coordinate.latitude, 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 would like to get the objects already sorted, and then extract them all, and then sort them in code.

Any advice appreciated.

+4
source share
1 answer

NSSortDescriptor must be initialized with a key string for an object property, not a query string. This means that you must use the distance formula as a method of your object.

After that, it doesn’t 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 does not work correctly, like lat. and for a long time. do not have the same scale if you are not at 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 the Law on Spherical Cosines :

 // assuming angles in radian, double separation = acos( sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(long1-long2) ); double distance = separation*earthRadius; 
+5
source

Source: https://habr.com/ru/post/1309105/


All Articles