我有一个非常罕见但会导致应用程序崩溃的奇怪错误。我无法重现它,但我终于找到了一份记录此内容的崩溃报告。 (我在下面发布了堆栈跟踪。我使用了屏幕截图,因为这里的引号函数弄乱了格式。那将是不可读的)
所以问题在点击按钮后开始,该按钮调用方法 closeButtonTapped
。
此方法应该淡出一个popup-view
(称为ExtendBitPopupView
)并保存用户输入的文本(details
属性我的数据模型之一)。
这就是 closeButtonTapped
方法:
func closeButtonTapped(tap: UITapGestureRecognizer) {
fadeOut { // fadeOut(completion:) just fades out the UI
if self.infoTextView.text != "Enter details..." {
self.entry.info = self.infoTextView.text
self.appDelegate.saveContext()
}
}
}
因此它将用户输入的文本作为 entry.info
保存到数据库中。
现在,了解一下上下文:ExtendBitPopupView
是一个 popup
,在显示所有 条目的
对象存在于数据库中。它使用 UITableView
上方淡入淡出NSFetchedResultsController
来管理数据。该表不显示 entry.info
属性。这仅在 ExtendBitPopupView
根据堆栈跟踪,应用程序在调用 controllerDidChange
方法时崩溃。我猜它调用此方法是因为 entry
已更改。
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .insert:
tableView.insertRows(at: [newIndexPath!], with: .automatic)
case .delete:
tableView.deleteRows(at: [indexPath!], with: .automatic)
case .update: // I guess this case is being used
let cell = tableView.cellForRow(at: indexPath!) as! BitCell
let entry = fetchedResultsController.object(at: indexPath!)
cell.configure(entry: entry)
case .move:
tableView.deleteRows(at: [indexPath!], with: .automatic)
tableView.insertRows(at: [newIndexPath!], with: .automatic)
}
}
崩溃日志中提到了第 224 行。就是这一行:
let cell = tableView.cellForRow(at: indexPath!) as! BitCell
我现在不明白为什么应用程序会崩溃。此外,它确实在 99% 的时间内正常工作。
我唯一的观察是,当它发生时,我输入了很多文本。但我不确定,因为到目前为止只发生过 3-4 次。
有人有什么想法吗?我不知道我可以尝试什么,也不知道如何重现这个错误。 如果您需要更多代码,请告诉我。我刚刚发布了崩溃日志中提到的代码。
提前致谢!
最佳答案
indexPath
是应用删除和插入之前的索引; newIndexPath
是应用删除和插入后的索引。
对于更新,您不关心它在插入和删除之前的位置 - 仅在插入和删除之后 - 所以使用 newIndexPath
而不是 indexPath
。这将修复当您同时更新和插入(或更新和删除)时可能发生的崩溃。
对于 move
,委托(delegate)说明插入之前它从哪里移动,以及插入和删除之后应该插入哪里。当您移动并插入(或移动并删除)时,这可能具有挑战性。我通过将 controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
中的所有更改保存到三个不同的 indexPath 数组中来修复此问题:插入、删除和更新。当您获得 move
时,在插入数组和删除数组中为其添加一个条目。在 controllerDidChangeContent:
中,删除数组降序排列,插入数组升序排列。然后应用更改 - 先删除,然后插入,然后更新。这将修复当您同时进行移动和插入(或移动和删除)时可能发生的崩溃。
section也是一样的道理。将部分更改保存在数组中,然后按顺序应用更改:删除(降序)、sectionDelete(降序)、sectionInserts(升序)、inserts(升序)、updates(任意顺序)。部分无法移动或更新。
关于ios - 应用程序在更新 UITableView 中显示的 CoreData 模型后崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41789817/