当前位置:  开发笔记 > 编程语言 > 正文

在更新正在UITableView中显示的CoreData模型后,应用程序崩溃

如何解决《在更新正在UITableView中显示的CoreData模型后,应用程序崩溃》经验,为你挑选了1个好方法。

我有一个奇怪的错误,非常罕见,但导致应用程序崩溃.我无法重现它,但我终于找到了一份记录此事件的崩溃报告.(我在下面发布了堆栈跟踪.我使用了截图,因为这里的引号函数搞砸了格式化.这将是不可读的)

因此,在点击调用该方法的按钮后,问题就开始了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数据库.

现在,上下文的一点:该ExtendBitPopupViewpopup上面一个淡入UITableView显示所有entry对象有在数据库中.它使用a NSFetchedResultsController来管理数据.该表未显示该entry.info属性.这只能在里面看到ExtendBitPopupView

根据堆栈跟踪,应用程序在调用controllerDidChange方法时崩溃.我猜它会调用这个方法因为entry已经改变了.

func controller(_ controller: NSFetchedResultsController, 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次.

有没有人有任何想法?我不知道我能尝试什么,我不知道如何重现这个bug.如果您需要更多代码,请告诉我们.我刚刚发布了崩溃日志中提到的代码.

提前致谢!

堆栈跟踪



1> Jon Rose..:

indexPath是删除和插入之前的索引; newIndexPath是删除和插入后应用的索引.

对于更新,您不必关心插入和删除之前的位置 - 仅在之后 - 因此newIndexPath请勿使用indexPath.这将修复当您更新并同时插入(或更新和删除)时可能发生的崩溃.

对于move代理人说它是从插入之前移动的位置以及在插入和删除之后应该插入的位置.当您进行移动和插入(或移动和删除)时,这可能具有挑战性.我通过将所有更改保存controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:到三个不同的数组,插入,删除和更新来修复此问题(您可以使用自定义对象或字典 - 任何适用于您的工作).当您move在插入数组和删除数组中为它添加条目时.在controllerDidChangeContent:排序中删除数组降序和插入数组升序.然后应用更改 - 首先删除,然后插入,然后更新.这将解决当您进行移动并同时插入(或移动和删除)时可能发生的崩溃.

处理部分涉及的更多,但它是相同的原则.将节更改保存在数组中,然后按顺序应用更改:删除(降序),sectionDelete(降序),sectionInserts(升序),插入(升序),更新(任何顺序).部分无法移动或更新.

推荐阅读
手机用户2502852037
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有