很遗憾,您找不到关于_nilOutReservedCurrentEventSnapshot__ 的信息
在线..
这可能与托管对象的快照生命周期有关。
当 Core Data 从持久存储中获取对象时,它会拍摄其状态的快照。快照是一个对象持久属性的字典——通常是它的所有属性以及与其具有一对一关系的任何对象的全局 ID。快照参与乐观锁定。当框架保存时,它会将每个已编辑对象的快照中的值与持久存储中当前对应的值进行比较。
_nilOutReservedCurrentEventSnapshot__ 未记录在案这一事实意味着不应发生此类行为。
我们所知道的是它是NSManagedObject 类的一个函数。
因此,导致错误unrecognized selector sent to instance 是因为在不是NSManagedObject 的对象上调用了_nilOutReservedCurrentEventSnapshot__,因为NSManagedObject 已被释放并且其他东西现在填充了它的内存。这是事实。
关于应用程序的性质及其 CoreData 设置的问题没有给出上下文,但可以推断它正在使用 父子并发模式。这很重要。
[图片取自here]
从我能找到的有关此错误的所有堆栈溢出问题中,看来它们都使用父子并发模式。
这个问题完全有可能是由于采用了这种模式而对 ManagedObjects 的实现或处理不当造成的。
可能使用父子上下文的情况是同步云数据或处理用户编辑某些内容时所做的更改,并选择丢弃或撤消所做的更改,这可以在后台线程上完成。
问题中还提到这是一种罕见的情况,并非每次都会发生。这意味着在进行特定保存或更改之前上下文可能很好,并且上下文以某种方式变得不同步,并且执行另一个保存会使应用程序崩溃。
来自有关在上下文之间同步更改的文档:
如果您在应用程序中使用多个托管对象上下文,Core Data 不会自动通知一个上下文对另一个上下文中的对象所做的更改。一般来说,这是因为上下文旨在成为一个便笺簿,您可以在其中单独更改对象,并且可以放弃更改而不影响其他上下文。
当子项被保存时,更改将被发送到父上下文,但如果父项已单独更改,则不会。强烈建议您永远更改父上下文;只能通过保存子上下文并从那里传播更改。
Possible reason for crash
有几件事可能会导致这种情况,但有两件事很突出:
1.由于关闭 iOS 应用程序中的模态视图或 OSX 应用程序中的工作表而从已处理的引用中释放 ManagedObject。
可能的解决方案:在获取 ManagedObjects 之前将子上下文的 retainsRegisteredObjects 属性设置为 true(然后在保存上下文后设置为 false 以避免进一步的潜在内存泄漏)。 warning!
例如。 ctx.retainsRegisteredObjects = true
2。对上下文的未处理更改。
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/ChangeManagement.html#//apple_ref/doc/uid/TP40001075-CH22-SW1
考虑一个具有两个托管对象上下文和一个持久存储协调器的应用程序。如果用户在第一个上下文 (moc1) 中删除了一个对象,您可能需要通知第二个上下文 (moc2) 一个对象已被删除。在所有情况下,moc1 都会通过 NSNotificationCenter 自动发布 NSManagedObjectContextDidSaveNotification 通知,您的应用程序应该注册并用作它需要采取的任何操作的触发器。此通知不仅包含有关已删除对象的信息,还包含有关已更改对象的信息。您需要处理这些更改,因为它们可能是删除的结果。大多数这些类型的更改都涉及瞬态关系或获取的属性。
这里可能的解决方案是:
因为这里没有其他信息可以推断导致错误的原因,而且我无法重现它。我建议尝试使用以下方法找到您的 ManagedObject 被释放的位置Instruments 中的僵尸分析。
如果随后将消息发送到这些已释放对象之一(现在是 NSZombie 对象),则会标记僵尸,应用程序崩溃,录制停止,并出现僵尸消息对话框。然后,您可以检查僵尸对象的保留和释放历史,以确定问题发生的确切位置。
https://github.com/iascchen/SwiftCoreDataSimpleDemo/blob/master/SwiftCoreDataSimpleDemo/CoreDataHelper.swift
希望有人可以更清楚地了解导致问题的原因。
+++++++++++++++++++++++++++++++++++
旁注:
父/子上下文可能会导致 UI 卡顿 - “every fetch request and every save operation will fully block the main thread while data is read or written to/from disk”. 这是因为每次获取都通过父上下文(在主线程上)拉到子上下文。
supporting SO answer
如果您使用这种方法,建议您将设计重新考虑为类似连接到同一个持久存储协调器的两个独立托管对象上下文 这可能会“避免”该问题将来发生。
[图片取自here]
您可以在linked article 中看到巨大的性能差异