Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

commitEditingStyle not being called

I'm trying to create a simple todo list app using core data. I've got the saving part right but when I try to use canEditRowAtIndexPath and commitEditingStyle all i can do is swipe left but no delete button.

Here's my code:

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle != .Delete{
        return
    }
    let appDelegate =
    UIApplication.sharedApplication().delegate as! AppDelegate
    let managedContext = appDelegate.managedObjectContext
    managedContext.deleteObject(people[indexPath.row])
    people.removeAtIndex(indexPath.row)
    tableView.beginUpdates()
    tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
    tableView.reloadData()
    tableView.endUpdates()

}

func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) - Bool { return true }

3 Answers

Nathan Tallack
Nathan Tallack
22,164 Points

Ok, here is how I am doing it in my core data app. And it works just fine.

    override func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
        return UITableViewCellEditingStyle.Delete
    }

    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        let entry = fetchedResultsController.objectAtIndexPath(indexPath)
        coreDataStack.managedObjectContext.deleteObject(entry as! NSManagedObject)
        coreDataStack.saveContext()
    }

    func controllerWillChangeContent(controller: NSFetchedResultsController) {
        tableView.beginUpdates()
    }

    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
        switch type {
        case NSFetchedResultsChangeType.Insert:
            tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: UITableViewRowAnimation.Automatic)
        case NSFetchedResultsChangeType.Delete:
            tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Automatic)
        case NSFetchedResultsChangeType.Update:
            tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Automatic)
        default:
            break
        }
    }

    func controllerDidChangeContent(controller: NSFetchedResultsController) {
        tableView.endUpdates()
    }

Now I am using core data so the work I am doing to update my managed objects is a little different to the work you are doing. But the key difference here is that I am overriding the builtin methods for the UITableViewController class that I am subclassing. Maybe that is what you are doing wrong. Maybe you cant call this stuff directly like you are because you are just being overwritten by those existing methods inside the superclass.

So try implementing your actions as separate functions, overriding those in the UITableViewController class, and you may get the results you desire. :)

Thank you so much! This helped me a lot! :)

Nathan Tallack
Nathan Tallack
22,164 Points

Glad we got there in the end. But I learnt how to do it now so that is a good thing for both of us. :)

Nathan Tallack
Nathan Tallack
22,164 Points

It could be because your table is not marked as editable. You can do it programatically or via the attributes editor.

Search the apple developer docs for "marking a table as editable". :)

Where can i find the editable checkbox in the attributes inspector?

Nathan Tallack
Nathan Tallack
22,164 Points

Apologies. I miss-rememebered that attribute. It is for enabling indenting when editing, not to allow editing.

After reading your code again I think I may have a suggestion.

Apple's guide on this method (which you can find here on their website) shows that you need to put all the code related to the delete action within the beginUpdates and endUpdates method calls. So it may be that you need to move your managed object methods inside there too.

Try it with your code looking like this.

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle != .Delete{
        return
    }

    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let managedContext = appDelegate.managedObjectContext 

    tableView.beginUpdates()
    managedContext.deleteObject(people[indexPath.row])
    people.removeAtIndex(indexPath.row)
    tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
    tableView.endUpdates()

    tableView.reloadData()

}

Unfortunately that's not working, I think it may be a bug, but I'll still put your answer as best answer. I'll report this to Apple. Thanks for your help anyway :)

Nathan Tallack
Nathan Tallack
22,164 Points

Do be sure to come back and update this post when you do find an answer so that we know how you fixed it. :)

Hey VeriS,

  1. Try moving the code inside the if block and moving putting the code related to the deletion between tableView.beginUpdates() and tableView.endUpdates().

  2. Change if editingStyle != .Delete to ==

  3. Make sure your function says override before it

  4. Remove the return statement

override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == .Delete {

        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        let managedContext = appDelegate.managedObjectContext

        tableView.beginUpdates()
        managedContext.deleteObject(people[indexPath.row])
        people.removeAtIndex(indexPath.row)
        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
        tableView.endUpdates()
        tableView.reloadData()

    }

}

It won't allow me to override it, without the override it's still the same. But thanks anyway :)