Search code examples
ioscore-datansfetchedresultscontroller

Delete a row from Core Data UITableView with custom button


I have a UITableView that is populated with cells by core data and an NSFetchedResultsController. I have a custom button on my custom cells, which I'm planning on using to delete the cell. It's very easy to add the standard swipe-to-delete, but I'd rather use this custom button. Does anyone know how I could hook up an action to the button that would delete the entry from the data model and delete the cell from the UITableView? I cannot find a good solution to this for the life of me.

EDIT:

This is the code I have to delete it using standard swipe-to-delete. Any way I could modify it to work with a button?

if (editingStyle == UITableViewCellEditingStyleDelete) {

    [self.tableView beginUpdates];

    // Delete the task 
    Task *taskToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
    NSLog(@"Deleting (%@)", taskToDelete.name);
    [self.managedObjectContext deleteObject:taskToDelete];
    [self.managedObjectContext save:nil];

    // Delete the row 
    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    [self performFetch];

    [self.tableView endUpdates];
}

Solution

  • General overview:

    1. Connect the button to an action on your controller, deleteRow:(id)sender;
    2. The sender will be the button. Get its superview, then the superview of its superview, and so on until you have a reference to the UITableViewCell. (Search in a loop using isKindOfClass:, don't assume the button is only 1, 2, 3 levels down.)
    3. Call your table view's indexPathForCell: method to convert the cell reference to an index path.
    4. Use objectAtIndexPath: on the fetched results controller to get the object.

    Then delete it! If you are handling the NSFetchedResultsController delegate methods they will take care of removing the deleted row.

    Sample code (typed without a compiler to check it):

    - (void)deleteRow:(id)sender
    {
        id view = [sender superview];
        while (view && ![view isKindOfClass:[UITableViewCell class]]) {
            view = [view superview];
        }
        UITableViewCell *cell = view;
        NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
        NSManagedObject *task = [fetchedResultsController objectAtIndexPath:indexPath];
        [self.managedObjectContext deleteObject:task];
        [self.managedObjectContext save:nil];
    }
    

    That's it. DO NOT try to remove the row from the table view. When the object is deleted, NSFetchedResultsController will detect the change and update your table view, assuming you set up the delegate methods as described in the documentation for NSFetchedResultsController. If you haven't, read the documentation (just option-double-click on "NSFetchedResultsController" in Xcode).