滑动删除UITableView单元格动画在swift 2中不起作用

时间:2015-10-05 14:55:36

标签: ios uitableview animation core-data swift2

滑动删除功能工作正常,但我无法添加动画,我尝试了一切,但没有任何效果。每当我添加动画代码时,应用程序会在删除单元格时崩溃。如果再次加载应用程序,您会发现该记录已被删除,这意味着删除成功。

我得到的崩溃错误是:

  

无效更新:第0部分中的行数无效   更新(1)后必须包含在现有部分中的行   等于之前该部分中包含的行数   更新(1),加上或减去插入或删除的行数   该部分(0插入,1删除)和加号或减号的数量   移入或移出该部分的行(0移入,0移出)。

我试过的动画代码块是:

        //1
        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        //2
        tableView.deleteRowsAtIndexPaths([indexPath],
            withRowAnimation: UITableViewRowAnimation.Automatic)

我也尝试删除这些代码,但它也没有用处:

fetchAndSetResults()  treatmentProtocolsTableView.reloadData()

swift文件中的整个代码都在这里,我注释掉了动画块,它运行正常。

import UIKit
import CoreData

class Tx_Protocols: UIViewController, UITableViewDataSource, UITableViewDelegate {

    //MARK: declaratoins.
    weak var secureTextAlertAction: UIAlertAction?

    //MARK: Core data related
    var txProtocols = [TreatmentProtocolData]()
    var selectedProtocol : TreatmentProtocolData? = nil

    @IBOutlet weak var treatmentProtocolsTableView: UITableView!


    //When button + is clicked, segue show add tx VC is initiated.
    @IBAction func plusButtonAddTxProtocol(sender: AnyObject) {
        self.performSegueWithIdentifier("showAddTxVC", sender: self)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        fetchAndSetResults()

        treatmentProtocolsTableView.delegate = self
        treatmentProtocolsTableView.dataSource = self
    }

    //When this is used, the data shows with a slight lag, slower.
    override func viewDidAppear(animated: Bool) {
        fetchAndSetResults()
        treatmentProtocolsTableView.reloadData()
    }

    //This is how you catch the app delegate core data fnxnality, GRABBING THE PROPERTY IN APP DELEGATE
    func fetchAndSetResults() {
        let app = UIApplication.sharedApplication().delegate as! AppDelegate
        let context = app.managedObjectContext
        let fetchRequest  = NSFetchRequest(entityName: "TreatmentProtocolData")

        do {
            let results = try context.executeFetchRequest(fetchRequest)
            self.txProtocols = results as! [TreatmentProtocolData]
        } catch let err as NSError {
            print(err.debugDescription)
        }
    }



    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier:"Cell")
        cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
        cell.textLabel!.adjustsFontSizeToFitWidth = true
        cell.textLabel!.font = UIFont.boldSystemFontOfSize(17)

        let treatmentProtocol = txProtocols[indexPath.row]
        cell.textLabel!.text = treatmentProtocol.title
        cell.imageView?.image = treatmentProtocol.getTxProtocolImage()

        return cell
    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return txProtocols.count
    }

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        tableView.deselectRowAtIndexPath(indexPath, animated: true)
        self.selectedProtocol = txProtocols[indexPath.row]
        self.performSegueWithIdentifier("showTxProtocol", sender: self)


    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        if segue.identifier == "showTxProtocol" {
        let detailVC = segue.destinationViewController as! ShowTxProtocolDetailVC
        detailVC.txProtocol = self.selectedProtocol
        }
    }


    //MARK: Edittable table, delete button functionality.
    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 app = UIApplication.sharedApplication().delegate as! AppDelegate
                let context = app.managedObjectContext
                //1
                let protocolToRemove =
                txProtocols[indexPath.row]

                //2
                context.deleteObject(protocolToRemove)

                //3
                do {
                    try context.save()
                } catch let error as NSError {
                    print("Could not save: \(error)")
                }

//                //1
//                tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
//                //2
//                tableView.deleteRowsAtIndexPaths([indexPath],
//                    withRowAnimation: UITableViewRowAnimation.Automatic)

                fetchAndSetResults()
                treatmentProtocolsTableView.reloadData()

            }
    }


}

感谢您的帮助

2 个答案:

答案 0 :(得分:7)

您需要封装在beginUpdates()endUpdates()内。此外,更新用于加载表视图的数据模型:

self.tableView.beginUpdates()
self.txProtocols.removeObjectAtIndex(indexPath.row) // Check this out 
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
self.tableView.endUpdates()

答案 1 :(得分:0)

基于Abhinav接受的答案,这是我的解决方案(Swift 3)。这在我的NSFetchedResultsControllerDelegate

中实现
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    self.tableView.beginUpdates()
}

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
    ...
    case .delete:
            // Delete from tableView
            removeFromSetsToDisplayByID(removeThisSet: myObject)
            tableView.deleteRows(at: [indexPath!], with: UITableViewRowAnimation.automatic)
    ...
}

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    self.tableView.endUpdates()
}