ioscore-datageolocationnssortdescriptornsfetchedresultscontroller

Locations in Core Data sorted by distance via NSFetchedResultsController?


I have a set of entity objects in my iOS Core Data database that describe something at a location. Let's call the entity Location. I have implemented this by having two attributes on Location that refer to the location - latitude and longitude, both doubles. There are other elements, like name.

I am using a NSFetchedResultsController to bind the entities to a UITableViewController. What I would like to do is have the results sorted by distance to a given CLLocationCoordinate2D. In an really ideal scenario, I'm able to refresh that list to recalculate the sort based on a new location. Therefore, this sort would depend on two keys, and a third "static" variable (one that doesn't vary across the items in the collection).

I think I could figure out how to do this if I was sorting an arbitrary list with NSSortDescriptors. However, I don't control how the sort descriptors are used in an NSFetchedResultsController.

Is there a way that I could configure my entities, my NSFetchedResultsController, my NSSortDescriptors, etc. to accomplish this? I suspect that the answer lies not in creating a fancy NSSortDescriptor but instead in creating a transient attribute in the entity that represents the distance-to-me, and recalculating that attribute periodically. However, I'm new enough to Core Data that I'm not sure how to best do this (iterate over all entities and recalculate a field). I'm also not sure if NSSortDescriptors will work on Transient attributes.


Solution

  • (From the comments:)

    A fetch request for a (SQLite based) Core Data store cannot use sort descriptors based on transient attributes or Objective-C based predicates.

    If you don't want to lose the advantages of a fetched results controller (like animated table view updates, automatic grouping into sections etc.) you have to pre-compute the distance to the current location and store it in a (persistent) attribute of your objects.

    Alternatively, you could fetch all objects and sort them in memory. In that case you can use arbitrary sort descriptors. But that cannot be combined with a fetched results controller, so you would have to register for changes in the managed object context and reload the table if necessary.