在UI中使用NSManagedObject作为数据对象

时间:2015-08-31 12:30:52

标签: ios core-data magicalrecord

我已经完成了简单的演示应用来说明问题。

假设我有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作为删除数据的上下文(模拟推送通知,可能需要删除一些数据)。

假设我将NSManagedObjectdetailVCContext传递给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()
        }
    }
}

2 个答案:

答案 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)。还传递新的上下文。
  • 如果发生了保存,请通知父控制器。它还应该保存其上下文并更新UI。