Search code examples
swifttableviewnsfetchedresultscontroller

UITableView row won't removed after being deleted


I'm having the problem where after i had deleted my tableview row, the row won't removed, here is the code, i had follow the tutorial online, and it successfully delete from data model, but it won't dismiss the deleted row unless I unwind back to previous screen and back to this view, why is it? :

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

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {

    if (editingStyle == UITableViewCellEditingStyle.Delete) {

        let product = frc.objectAtIndexPath(indexPath) as! Product

        let productName = product.name

        let message = (MCLocalization.sharedInstance.stringForKey("cart_remove_one_item_message",  replacements: ["%s" : productName!]))
        let alert = UIAlertController(title: (MCLocalization.sharedInstance.stringForKey("cart_remove_title")), message: message, preferredStyle: UIAlertControllerStyle.Alert)

        let OKAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: {
            (_)in

            let managedObject : NSManagedObject = self.frc.objectAtIndexPath(indexPath) as! NSManagedObject
            self.moc.deleteObject(managedObject)
            self.tableView.reloadData()

            do {
                try self.moc.save()  
            } catch {
                print("Failed to save.")
                return
            }
        })

        alert.addAction(OKAction)
        alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))
        self.presentViewController(alert, animated: false, completion: nil)
    }  
}

Solution

  • You need to remove object from your array also then reload your tableView after moc.save() successfully.

    let managedObject : NSManagedObject = self.frc.objectAtIndexPath(indexPath) as! NSManagedObject
    self.moc.deleteObject(managedObject)
    do {
       try self.moc.save()
    
    } catch {
        print("Failed to save.")
        return
    }
    

    Edit: You need to add that in your question that you are using NSFetchedResultsController, Now i think you have set the delegate with your self.frc.delegate = self, then add this delegate method also remove the reloadData there is no need for that now.

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

    Fore more detail about NSFetchedResultsController check tutorials it will help you.