Search code examples
iosobjective-cuitableviewcore-datansfetchedresultscontroller

Attempting to reordering UITableView using an NSFetchedResultsController


I am attempting to edit the order of my UITableView while using Core Data and an NSFetchedResultsController. As I understand, Core Data does not have a built in method for rearranging objects in a Core Data model.

The idea was to create an array, reorder my objects there, and then write that data back to my model.

NSFetchedResultsController

-(NSFetchedResultsController *) fetchedResultsController {
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
}

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSManagedObjectContext *context = [self managedObjectContext];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"List" inManagedObjectContext:context];
    [fetchRequest setEntity:entity];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"listName" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor, nil];
        fetchRequest.sortDescriptors = sortDescriptors;
        _fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
        _fetchedResultsController.delegate = self;
    return _fetchedResultsController;
}

moveRowAtIndexPath

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath; {
    NSMutableArray *toDoItems = [[self.fetchedResultsController fetchedObjects] mutableCopy];
    NSManagedObject *managedObject = [[self fetchedResultsController] objectAtIndexPath:sourceIndexPath];
    [toDoItems removeObject:managedObject];
    [toDoItems insertObject:managedObject atIndex:[destinationIndexPath row]];
    int i = 0;
    for (NSManagedObject *moc in toDoItems) {
        [moc setValue:[NSNumber numberWithInt:i++] forKey:@"listName"];
    }

    [self.managedObjectContext save:nil];
}

When I hit my Edit button, I can rearrange the rows but as soon as I let the row go, my app crashes. Im not getting any kind of stack trace in the console when it crashes.

I set a breakpoint on exception and it seems to be crashing on this line

[moc setValue:[NSNumber numberWithInt:i++] forKey:@"listName"];

My key name is correct. But I now realize this is completely wrong in that I am trying to set this as a number and that shouldnt be the case.

Any suggestion or push in the right direction would be appreciated.


Solution

  • Either amend your code to set a string value for the listName, something like this:

    [moc setValue:[NSString stringWithFormat:"%d",i++] forKey:@"listName"];
    

    (but beware because by default this will sort as a string, so 11 comes before 2, etc).

    So, better, add an integer attribute to your model, and use that to sort the fetched results controller.