NSSortDescriptor - sort by location

元气小坏坏 提交于 2019-12-22 09:11:21

问题


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?


回答1:


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.




回答2:


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.




回答3:


You can't sort by lat/Lon anyway, you'll need to compute distance for each point and sort by that. Or fetch a range of lat/Lon values near the user, fetch that subset, compute distance for them and display. range would be like user's lat +/- 0.1 degrees, etc for the fetch.




回答4:


I would recommend the following approach:

See the 'Geo-Location Predicate' section of http://www.objc.io/issue-4/core-data-fetch-requests.html

It gets approximate results using a predicate and then sorts them accurately in-memory.



来源:https://stackoverflow.com/questions/12027769/nssortdescriptor-sort-by-location

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!