Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy aren't multiple NSSortDescriptors working with NSFetchedResultsController
    text
    copied!<p>I have a controller with a UITableView which is displaying a list of "Item" objects, the items are like checkbook entries. Everything seems to be working properly other than sorting. I'll describe the sorting I'm looking for below, but currently the records are being displayed in the order they were created. The Item objects (NSManagedObjects) have properties that include date (NSDate), amount (NSDecimalNumber) and entry (Entry is a NSManaged object that is a relationship to Item).</p> <p>In the application you create an entry with a type (NSNumber 0 == credit, 1 = debit), title, description etc. Then you add 1 or more Item objects that have an amount, date etc.</p> <p>I'd like the items to be grouped by date in table view sections so all the items that share the same date will be in the same section. Within each section they should be sorted with first by type (credits first then debits) then by amount descending. Something like this within a section:</p> <h2>July 3, 2012</h2> <ul> <li>Credit: 900</li> <li>Debit: (25)</li> <li>Debit: (15)</li> </ul> <h2>August 7, 2012</h2> <ul> <li>Credit: 1000</li> <li>Credit: 900</li> <li>Credit: 100</li> <li>Credit: 25</li> <li>Debit: (700)</li> <li>Debit: (450)</li> <li>Debit: (25)</li> </ul> <p>The ViewController itself is a UITableViewDelegate, UITableViewDataSource, and NSFetchedResultsControllerDelegate.</p> <p>Here is the NSFetchedResultsController getter method:</p> <pre><code>- (NSFetchedResultsController *)aFetchedResultsController { if (_aFetchedResultsController != nil) { return _aFetchedResultsController; } NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(date &gt;= %@) AND (date &lt;= %@)", startDate, endDate]; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Item" inManagedObjectContext:self.context]; [fetchRequest setEntity:entity]; [fetchRequest setPredicate:predicate]; NSSortDescriptor *sortDate = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:YES]; NSSortDescriptor *sortType = [[NSSortDescriptor alloc] initWithKey:@"entry.type" ascending:YES]; NSSortDescriptor *sortAmount = [[NSSortDescriptor alloc] initWithKey:@"amount" ascending:NO]; [fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDate, sortType, sortAmount, nil]]; [fetchRequest setFetchBatchSize:20]; NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.context sectionNameKeyPath:@"day" cacheName:@"Root"]; self.aFetchedResultsController = theFetchedResultsController; _aFetchedResultsController.delegate = self; return _aFetchedResultsController; }//end </code></pre> <p>View Did Load:</p> <pre><code>- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. NSDate *today = [NSDate new]; NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; NSDateComponents *offsetComponents = [[NSDateComponents alloc] init]; [offsetComponents setMonth:-1]; //1 month ago startDate = [gregorian dateByAddingComponents:offsetComponents toDate:today options:0]; [offsetComponents setMonth:1]; //1 month ahead endDate = [gregorian dateByAddingComponents:offsetComponents toDate:today options:0]; //set the MOC self.context = [((AppDelegate *)[[UIApplication sharedApplication] delegate]) managedObjectContext]; [self fetchRecords]; }//end viewDidLoad </code></pre> <p>And the method that actually fetches the records:</p> <pre><code>-(void)fetchRecords{ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(date &gt;= %@) AND (date &lt;= %@)", startDate, endDate]; [[self.aFetchedResultsController fetchRequest] setPredicate:predicate]; [NSFetchedResultsController deleteCacheWithName:@"Root"]; NSError *error; if (![[self aFetchedResultsController] performFetch:&amp;error]) { // Update to handle the error appropriately. NSLog(@"Unresolved error %@, %@", error, [error userInfo]); exit(-1); // Fail }//end if [_tableView reloadData]; }//end fetchRecords </code></pre> <p>"day" is an Item instance method that I'm using to have the UITableView section headers display the formatted date string:</p> <pre><code>- (NSString *)day { NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; dateFormatter.dateStyle = NSDateFormatterFullStyle; return [dateFormatter stringFromDate:self.date]; }//end day </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload