Ios 删除带有动画的UITableViewCell(错误/崩溃)

Ios 删除带有动画的UITableViewCell(错误/崩溃),ios,uitableview,swift,core-data,Ios,Uitableview,Swift,Core Data,我想用动画从UITableView中删除UITableViewCell核心数据对象。我为此编写了以下代码: func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { let mySelectedCell:UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)! //1 let appD

我想用动画从
UITableView
中删除
UITableViewCell
核心数据对象。我为此编写了以下代码:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    let mySelectedCell:UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!

    //1
    let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate

    let managedContext = appDelegate.managedObjectContext!

    //2
    let fetchRequest = NSFetchRequest(entityName:"Person")

    //3
    mySelectedCell.backgroundColor = green
    mySelectedCell.detailTextLabel?.text = "Done"
    mySelectedCell.accessoryType = UITableViewCellAccessoryType.Checkmark        

    let person = people[indexPath.row]
    managedContext.deleteObject(person)
    self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Right)
}
我不知道为什么,但是如果我选择一个我想删除的单元格,应用程序就会崩溃

2015-03-29 18:00:10.776 MyApp[3001:79507] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-3318.93/UITableView.m:1582
崩溃行:
self.tableView.deleteRowsAtIndexPaths([indexPath],withRowAnimation:.Right)

有人知道我做错了什么吗

更新:

tableView.beginUpdates()

var numberItems:Int = people.count

self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Right)
numberItems -= [indexPath].count // something like [indexPath].count

tableView.endUpdates()


func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    application.applicationIconBadgeNumber = people.count
    return people.count
}
新错误:


在这行代码中:
tableView.endUpdates()

您必须以以下方式将您的方法
deleteRowsAtIndexPaths
放在这两个方法中:

var path = [NSIndexPath]()

// This is only a example with the index [0..numberOfItemsToDelete-1]
for (var i = 0; i < numberOfItemsToDelete; i++) {
    path.append(NSIndexPath(forRow: i, inSection: 0))
}

tableView.beginUpdates()    

self.tableView.deleteRowsAtIndexPaths(path, withRowAnimation: .Right)
self.numberOfItems -= theNumberYouDeletedAbove // something like [indexPath].count

tableView.endUpdates()
其中
numberOfItems
与用于显示项目的数组大小匹配


我希望这对您有所帮助。

如果表视图使用 删除对象的方法是从托管对象上下文中删除该对象:

let context = self.fetchedResultsController.managedObjectContext
context.deleteObject(self.fetchedResultsController.objectAtIndexPath(indexPath) as NSManagedObject)
当然,保存上下文以使更改永久化

然后,更新表视图由 获取的结果控制器委托方法

func controllerWillChangeContent(controller: NSFetchedResultsController)
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType)
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?)
func controllerDidChangeContent(controller: NSFetchedResultsController)
您将在中找到这些方法的典型实现 文档,如果您还没有 已经实施了

此外,您不应该在数据库中有已获取对象的“副本”
people
array。直接使用“获取结果”控制器 在表视图数据源方法中,例如:

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return self.fetchedResultsController.sections?.count ?? 0
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let sectionInfo = self.fetchedResultsController.sections![section] as NSFetchedResultsSectionInfo
    return sectionInfo.numberOfObjects
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
    self.configureCell(cell, atIndexPath: indexPath)
    return cell
}
如果您在Xcode中创建一个新的“主细节+核心数据应用程序”
然后,您将获得所需的所有必要模板代码。

首先,删除这一行,它试图复制并涉及managedContext作业,从而导致崩溃

self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Right)
第二,现在您应该能够在没有崩溃和动画的情况下删除

第三,让NSFetchedResultsController使用“didChange”处理程序删除并触发动画

在类定义中,并在类中设置委托,例如

yourResultsController.delegate = self

应用程序不仅仅是崩溃。崩溃时,您收到的具体错误消息是什么?哪一行崩溃了?我更新了我的问题。你在使用获取结果控制器吗?是的,我在使用获取结果控制器。我再次更新了我的问题。我发布了您说我应该使用的代码和以下错误。@horst What's
[indepath]
?我认为是
people[indexPath.row]
相反,请尝试删除一个one@horst请参阅更新的答案,了解如何传递答案的
[nsindepath]
数组存储库。但我也喜欢用动画删除对象。你知道我怎么做吗?@horst:你是说用动画删除表格视图单元格?正如我所说,如果正确实现了NSFetchedResultsControllerDelegate方法,那么应该自动完成这项工作。例如,
func控制器(控制器:nsfetchedresultscoontroller,didChangeObject…
调用
tableView.deleteRowsAtIndexPaths([indexPath!],withRowAnimation:.Fade)
如果是
.Delete
事件。在Xcode中创建一个全新的“主细节+核心数据应用程序”,然后您将看到它是如何工作的如果您需要更多信息,请告诉我。@horst:这可能意味着managedObjectContext为零。谢谢您的帮助!现在它工作得很好。我只想知道如何通过NSFetchedResultsController更新CoreData对象。你知道我怎么做吗
newManagedObject.setValue(日期,forKey:“datum”)
不起作用。@horst:要更新现有对象,必须先获取它,然后更改属性。
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Right)
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, 
    didChange anObject: Any, 
    at indexPath: IndexPath?, 
    for type: NSFetchedResultsChangeType, 
    newIndexPath: IndexPath?) 
    {
       print(indexPath)
       if type == .delete{
           tableView.deleteRows(at: [indexPath!], with: .automatic)
    }
}

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    tableView.endUpdates()
    //0.4 sec delay before refreshing the table
    DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.4) {
        self.refresh()
    }
}
func refresh(){
    tableView.reloadData() 
}
NSFetchedResultsControllerDelegate
yourResultsController.delegate = self