Custom sort with NSFetchedResultController (subclass NSSortDescriptor)

I want to provide custom sorting using NSFetchedResultsController and NSSortDescriptor.

As a custom sort through the message NSSortDescriptor - (id) initWithKey: ascending: selector: impossible (see here ), I tried to use the derived class NSSortDescriptor to override the message compareObject: toObject :.

My problem is that the compareObject: toObject: method is not always called. It seems that it is only called when the data is already in memory. There is some optimization that uses database-based sorting instead of compareObject: toObject when data is retrieved from storage for the first time. (see here ).

My question is: how to get NSFetchedResultscontroller to use compareObject: toObject: message to sort data? (and whether it will work with a large data set)

One solution is to use binary storage instead of sqlite storage, but I don't want to do this.

Another solution:
-call executeFetch to sort data through SQL (compareObject is not called)
-make data changes and undo it.
-call executeFetch again (compareObject method is called)
It works in my case, but it’s a hack, and I’m not sure that it will always work (especially with a large data set (larger than the lot size)).

UPDATED: You can play a sample sample of CoreDataBooks.
In RootViewController.m add this ugly hack:

- (void)viewWillAppear:(BOOL)animated { Book* book = (Book *)[NSEntityDescription insertNewObjectForEntityForName:@"Book" inManagedObjectContext:[self fetchedResultsController].managedObjectContext]; [[self fetchedResultsController] performFetch:nil]; [[self fetchedResultsController].managedObjectContext deleteObject:book]; [self.tableView reloadData]; } 

In RootViewController.m, replace the sort descriptor code with:

 MySortDescriptor *myDescriptor = [[MySortDescriptor alloc] init]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:myDescriptor, nil]; [fetchRequest setSortDescriptors:sortDescriptors]; 

Add class MySortDescriptor:

 @implementation MySortDescriptor -(id)init { if (self = [super initWithKey:@"title" ascending:YES selector:@selector(compare:)]) { } return self; } - (NSComparisonResult)compareObject:(id)object1 toObject:(id)object2 { //set a breakpoint here return [[object1 valueForKey:@"author" ] localizedCaseInsensitiveCompare:[object2 valueForKey:@"author" ] ]; } //various overrides inspired by [this blog post][3] - (id)copy { return [self copyWithZone:nil ]; } - (id)mutableCopy { return [self copyWithZone:nil ]; } - (id)mutableCopyWithZone:(NSZone *)zone { return [self copyWithZone:zone ]; } - (id)copyWithZone:(NSZone*)zone { return [[MySortDescriptor alloc] initWithKey:[self key] ascending:[self ascending] selector:[self selector]]; } - (id)reversedSortDescriptor { return [[[MySortDescriptor alloc] initWithKey:[self key] ascending:![self ascending] selector:[self selector]] autorelease]; } @end 
+6
iphone core-data nsfetchedresultscontroller nssortdescriptor
source share
1 answer

Regarding your question and comments. You will need to pull the objects into memory to sort them. Once they are in memory, you can use the convenience method to determine the distance from the point.

To reduce the number of objects that you retrieve into memory, you can calculate the maximum and minimum values, and then filter them, reducing the search radius before sorting.

Cannot sort by computed value if it is not in memory.

+6
source share

All Articles