xcode iOS8 Swift:deleteRowsAtIndexPaths 崩溃
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25588779/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS8 Swift: deleteRowsAtIndexPaths crashes
提问by Nate Birkholz
I am having some trouble with deleting a row from my tableView in Swift, iOS 8, Xcode 6 Beta 6. Every time I try to delete a row I get an error along the lines of
我在 Swift、iOS 8、Xcode 6 Beta 6 中从我的 tableView 中删除一行时遇到了一些麻烦。每次我尝试删除一行时,我都会收到如下错误
Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-3302.3.1/UITableView.m:1581 2014-08-30 20:31:00.971 Class Directory[13290:3241692] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 1. The number of rows contained in an existing section after the update (25) must be equal to the number of rows contained in that section before the update (25), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).
-[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-3302.3.1/UITableView.m:1581 2014-08-30 20:31:00.971 Class Directory[13290:3241692] 中的断言失败 *** 终止应用程序未捕获的异常“NSInternalInconsistencyException”,原因:“无效更新:第 1 节中的行数无效。更新后现有节中包含的行数 (25) 必须等于更新前该节中包含的行数(25),加上或减去从该部分插入或删除的行数(0 插入,1 删除)并加上或减去移入或移出该部分的行数(0 移入,0 移出)。
I have read all the answers to this frequent problem, here, and feel I have fulfilled the conditions recommended.The item seemsto be removed from the data model -- when I reload the app, the deleted item is gone from the table -- but there seem to be some remnants in the appropriate sqlite file and of course the math doesn't add up. The println that spits out the indexPath shows the correct Section and Row. I'm very puzzled. This should be straightforward but I am missing something dumb I am sure, I suspect in the data model deletion. Full project on Github.
我在这里阅读了这个常见问题的所有答案,并且觉得我已经满足了推荐的条件。该项目似乎已从数据模型中删除——当我重新加载应用程序时,删除的项目从表中消失了——但在适当的 sqlite 文件中似乎有一些残余物,当然数学不会加起来. 输出 indexPath 的 println 显示了正确的 Section 和 Row。我很困惑。这应该很简单,但我确信我遗漏了一些愚蠢的东西,我怀疑删除了数据模型。Github上的完整项目。
func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
return fetchedResultController.sections.count
}
func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
return fetchedResultController.sections[section].numberOfObjects
}
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell = tableViewMain.dequeueReusableCellWithIdentifier("CellMain", forIndexPath: indexPath) as UITableViewCell
let personForRow = fetchedResultController.objectAtIndexPath(indexPath) as Person
cell.textLabel.text = personForRow.fullName()
return cell
}
func tableView(tableView: UITableView!, canEditRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
return true
}
func tableView(tableView: UITableView!, editingStyleForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.Delete
}
func tableView(tableView: UITableView!, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath!) {
println("section and row \(indexPath.section) \(indexPath.row) ")
if (editingStyle == UITableViewCellEditingStyle.Delete) {
let personForRow : NSManagedObject = fetchedResultController.objectAtIndexPath(indexPath) as Person
context?.deleteObject(personForRow)
context?.save(nil)
tableViewMain.beginUpdates()
tableViewMain.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
tableViewMain.endUpdates()
}
采纳答案by Imanou Petit
It's easy to reproduce your crash with a Xcode Core Data Master-Detail template project. As a general rule, when you use NSFetchedResultsController
, you should really use NSFetchedResultsControllerDelegate
(you have declared it but don't use it).
使用 Xcode Core Data Master-Detail 模板项目可以轻松重现崩溃。作为一般规则,当您使用 时NSFetchedResultsController
,您应该真正使用NSFetchedResultsControllerDelegate
(您已声明它但不使用它)。
Delete those lines in your tableView:commitEditingStyle:forRowAtIndexPath:
method:
删除tableView:commitEditingStyle:forRowAtIndexPath:
方法中的这些行:
tableViewMain.beginUpdates()
tableViewMain!.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Fade)
tableViewMain.endUpdates()
And add those lines to your viewController class:
并将这些行添加到您的 viewController 类中:
func controllerWillChangeContent(controller: NSFetchedResultsController) {
tableViewMain.beginUpdates()
}
func controller(controller: NSFetchedResultsController!, didChangeSection sectionInfo: NSFetchedResultsSectionInfo!, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
switch type {
case .Insert:
tableViewMain.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
case .Delete:
tableViewMain.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
default:
return
}
}
func controller(controller: NSFetchedResultsController!, didChangeObject anObject: AnyObject!, atIndexPath indexPath: NSIndexPath!, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath!) {
switch type {
case .Insert:
tableViewMain.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
case .Delete:
tableViewMain.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
case .Update:
return
//Should also manage this case!!!
//self.configureCell(tableView.cellForRowAtIndexPath(indexPath), atIndexPath: indexPath)
case .Move:
tableViewMain.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
tableViewMain.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
default:
return
}
}
func controllerDidChangeContent(controller: NSFetchedResultsController!) {
tableViewMain.endUpdates()
}
This should fix your problem.
这应该可以解决您的问题。
回答by drewag
I believe this is simply a caching problem. Your fetchedResultController
is not going to automatically refetch your results as it caches its results. That means that when tableView:numberOfRowsInSection:
is called again, the results count is still returning 25 even though you deleted an item.
我相信这只是一个缓存问题。您fetchedResultController
不会在缓存结果时自动重新获取结果。这意味着当tableView:numberOfRowsInSection:
再次调用时,即使您删除了一个项目,结果计数仍然返回 25。