使用NSManagedObject在UI

问题描述:

数据对象我已经做了简单的演示应用程序来说明问题。使用NSManagedObject在UI

假设我有大师 - 具有以下上下文结构细节的应用:

managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType) 

let detailVCContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType) 
detailVCContext.parentContext = managedObjectContext 

let deleteContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType) 
deleteContext.parentContext = managedObjectContext 

我用detailVCContext作为在细节VC编辑/撤销/保存数据的暂存器。

我用deleteContext作为删除数据的上下文(模拟推送通知,可能需要删除一些数据)。

假设我将NSManagedObjectdetailVCContext传递给DetailViewController,其中显示来自模型的数据并对其进行修改。打开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() 
       } 
      }) 

这导致accesing详情VC模型的任何财产(或保存)导致

***终止由于应用未捕获的异常 'NSObjectInaccessibleException',理由是: 'CoreData不能履行 过错' 0xd0000000000c0000 '


这是否意味着我不能使用NSManagedObject作为数据模型?我是否需要将其包装在其他课程中?

* UPDATE *

貌似我通过我的代码混淆。

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() 
     } 
    } 
} 

就像捉鬼敢死队教过你,不要过线

的首要规则是,任何试图进行跨线程边界的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操作来说并不好。

+0

我已根据您的建议更新了代码,但仍存在相同的问题 – user1284151

+0

对象来自哪里。它的地址看起来不正确。 –

+0

是的,原因地址是无效的,因为在打开DetailVC后,我从存储中删除对象 – user1284151

你想要一个丢弃的上下文作为暂存器。用户编辑,如果他保存你保存的上下文,如果他取消你只需把它扔掉。我会按照这个模式:

  • 呈现细节控制器之前,创建一个新的ad-hoc孩子方面有MainQueueConcurrencyType
  • 通过NSManagedObjectID获取要编辑的对象并将其传递给详细控制器(例如,在prepareForSegue中)。还传递给它新的上下文。
  • 如果发生保存,通知父控制器。它还应该保存其上下文并更新UI。