我已经完成了简单的演示应用来说明问题。
假设我有Master - Detail应用程序,具有以下上下文结构:
managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
let detailVCContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
detailVCContext.parentContext = managedObjectContext
let deleteContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
deleteContext.parentContext = managedObjectContext
我使用detailVCContext
作为暂存器来编辑/撤消/保存VC中的数据。
我使用deleteContext
作为删除数据的上下文(模拟推送通知,可能需要删除一些数据)。
假设我将NSManagedObject
和detailVCContext
传递给Detail ViewController,我在其中显示模型中的数据并对其进行修改。在打开DetailVC之后我立即从deleteContext
中的存储中删除了这个模型:
let deletableID = object.objectID
deleteContext.performBlock({ () -> Void in
let itemInContext = deleteContext.objectWithID(deletableID)
deleteContext.deleteObject(itemInContext)
var error: NSError?
deleteContext.save(&error)
if (error != nil) {
abort()
}
deleteContext.parentContext?.save(&error)
if (error != nil) {
abort()
}
})
这导致访问详细VC中的模型的任何属性(或保存它)导致
***由于未捕获的异常终止应用' NSObjectInaccessibleException',原因:' CoreData无法满足 错误为' 0xd0000000000c0000 ''
这是否意味着我不能将NSManagedObject用作数据模型?我需要将它包装在其他类中吗?
*更新*
看起来我对我的代码感到困惑。
DetailVC
中与UI相关的所有代码都适用于managedObjectContext
(我传递模型对象,在managedObjectContext中获取)。
当我将对象传递给DetailVC
时,我会这样做:
if let detail: AnyObject = self.detailItem {
if let label = self.detailDescriptionLabel {
label.text = detail.valueForKey("timeStamp")!.description
}
}
当我按下保存按钮时,我会这样做:
@IBAction func saveButtonClicked(sender: AnyObject) {
detailItem?.setValue(NSDate(), forKey: "timeStamp")
let saveId = detailItem!.objectID
detailVCContext.performBlock { () -> Void in
let itemInContext = self.detailVCContext.objectWithID(saveId)
var error: NSError?
self.detailVCContext.save(&error)
if let error = error {
abort()
}
}
}
答案 0 :(得分:0)
就像捉鬼敢死队教过你一样,不要越过线程
主要规则是任何在线程边界上携带NSManagedObject
的尝试都是不安全的。您发送的最多信息是managedObjectID
就在这里你传递对象
deleteContext.performBlock({ () -> Void in
let itemInContext = deleteContext.objectWithID(object.objectID)
所以你能做的就是
let deletableID = object.objectID
deleteContext.performBlock({ () -> Void in
let itemInContext = deleteContext.objectWithID(deletableID)
不相关但也可能导致你问题的是这个...
let detailVCContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
detailVCContext.parentContext = managedObjectContext
此上下文对UI操作没有好处,因为所有UI工作必须在主队列上进行。
答案 1 :(得分:0)
你想要一个丢弃的上下文作为暂存器。用户编辑,如果他保存您保存上下文,如果他取消您只需将其丢弃。我会遵循这种模式:
MainQueueConcurrencyType
创建一个新的临时子上下文。 NSManagedObjectID
获取要编辑的对象,并将其传递给详细控制器(例如prepareForSegue
)。还传递新的上下文。