删除 CoreData 对象会导致 EXC_BAD_INSTRUCTION
Posted
技术标签:
【中文标题】删除 CoreData 对象会导致 EXC_BAD_INSTRUCTION【英文标题】:Deleting CoreData object results in EXC_BAD_INSTRUCTION 【发布时间】:2020-06-21 19:32:32 【问题描述】:我有一个基于列表的应用程序。为了支持将新元素添加到列表中,我所做的是在动作处理程序中创建一个新对象,并将其传递给详细信息视图。如果用户取消详细信息视图,我想删除该对象 - 当我这样做时,我得到一个 EXC_BAD_INSTRUCTION
。
一定有一些线程问题正在发生。
如果我在创建笔记后立即删除它(作为测试),它可以工作:
Button(action:
self.newNote = NoteDataManager.makeNote(moc: self.moc, folder: self.savingFolder)
// DELETE immediately, as a test
self.moc.delete(self.newNote!)
self.showNewNoteView = true
)
Image(systemName: "square.and.pencil")
.sheet(isPresented: self.$showNewNoteView)
CreateNoteView(newNote: self.newNote!, cancelAction:
// DO NOTHING here (for now)
)
但是,如果我在 cancelAction
的处理程序中删除它(当用户点击取消按钮时调用它),我会得到异常:
Button(action:
self.newNote = NoteDataManager.makeNote(moc: self.moc, folder: self.savingFolder)
self.showNewNoteView = true
)
Image(systemName: "square.and.pencil")
.sheet(isPresented: self.$showNewNoteView)
CreateNoteView(newNote: self.newNote!, cancelAction:
// MOVING the delete action here causes EXC_BAD_INSTRUCTION
self.moc.delete(self.newNote!)
)
我的猜测是这是某种线程问题之类的。有没有人遇到过这个问题并知道如何解决这个问题?看来应该可以了……
【问题讨论】:
尝试将该行分成两行。第一个是let n = self.newNote!
,第二个是self.moc.delete(n)
。我想知道是!
导致它崩溃(即newNote
为零)。
不是——我试过了,谢谢你的建议!我还浏览了调试器,动作处理程序成功了。崩溃发生在 SwiftUI 框架代码中。
【参考方案1】:
Core Data 旨在在多线程环境中工作。然而,并不是 Core Data 框架下的每个对象都是线程安全的。要在多线程环境中使用 Core Data,请确保:
托管对象上下文在初始化时绑定到与其关联的线程(队列)。 从上下文中检索的托管对象绑定到上下文所绑定的同一个队列。避免问题
一般来说,避免在与用户无关的主队列上进行数据处理。数据处理可能是 CPU 密集型的,如果在主队列上执行,可能会导致用户界面无响应。如果您的应用程序将处理数据,例如从 JSON 将数据导入 Core Data,请创建私有队列上下文并在私有上下文上执行导入。 不要在队列之间传递 NSManagedObject 实例。这样做可能会导致数据损坏和应用程序终止。当需要将托管对象引用从一个队列传递到另一个队列时,请使用 NSManagedObjectID 实例。 您可以通过调用 NSManagedObject 实例上的 objectID 访问器来检索托管对象的托管对象 ID。
根据苹果documentation
并发是处理多个数据的能力 同时排队。如果您选择在 Core 中使用并发 数据,还需要考虑应用环境。为了 大多数情况下,AppKit 和 UIKit 不是线程安全的。在 macOS 中 特别是,Cocoa 绑定和控制器不是线程安全的——如果你 正在使用这些技术,多线程可能会很复杂。
使用私有队列支持并发
一般来说,避免在非主队列上做数据处理 用户相关。数据处理可能是 CPU 密集型的,如果是 在主队列上执行,它可能导致在主队列中无响应 用户界面。如果您的应用程序将处理数据,例如 将数据从 JSON 导入 Core Data,创建一个私有队列 上下文并在私有上下文上执行导入。
【讨论】:
以上是关于删除 CoreData 对象会导致 EXC_BAD_INSTRUCTION的主要内容,如果未能解决你的问题,请参考以下文章