我的应用程序有时会将不一定要保存的对象插入到托管对象上下文中。例如,当我启动“添加实体”模式时,我创建一个托管对象并将其分配给该模式。如果用户从该模式保存,我会保存上下文。如果他取消,我会删除该对象并且无需保存。
我现在引入了一个“导入”功能,可以切换到我的应用程序(使用 URL 方案)并添加一个实体。由于这些模式之一可能是打开的,因此此时保存上下文并不安全。即使用户取消,为模态创建的瞬态对象也将被保存,并且不能保证删除(来自取消操作)稍后会被保存 - 用户可能会退出应用程序。
同样,我不能在应用程序退出时简单地进行保存。如果此时模式打开,临时对象将被错误保存。
为了解决这个问题,我尝试使用子上下文,如上所述here http://www.cocoanetics.com/2012/07/multi-context-coredata/。读完我能找到的所有内容后,我仍然有几个问题:
我应该为每个上下文使用哪种并发类型?请记住,我这样做并不是为了性能/线程优势。我知道如果要具有子上下文,我不能将 NSConfinementConcurrencyType 用于主上下文,但我不确定其他两个选项中哪一个最适合。对于子上下文,是否需要匹配?或者我可以在这里使用限制类型吗?我尝试了多种组合,似乎都工作正常,但我想知道哪种组合适合我的要求。
(附带问题)为什么只有使用 iVar 类才能使其工作?我认为我应该能够在创建临时上下文的方法中声明它,然后使用entity.managedObjectContext 引用它。但当我访问它时它似乎为零?如果我改用 iVar 来保存引用,这个问题就会得到纠正。
-
将更改传播到主要上下文的正确方法是什么?我已经看到在每个上下文上使用不同的块包装实现的各种评论。这取决于我的并发类型吗?我当前的版本是:
//save the new entity in the temporary context
NSError *error = nil;
if (![myObject.managedObjectContext save:&error]) {NSLog(@"Error - unable to save new object in its (temporary) context");}
//propogate the save to the main context
[self.mainContext performBlock:^{
NSError *error2 = nil;
if (![self.mainContext save:&error2]) {NSLog(@"Error - unable to merge new entity into main context");}
}];
当我的用户保存时,它会向其委托(我的主视图控制器)发送一条消息。委托被传递给添加的对象,并且它必须在主上下文中找到相同的对象。但是当我在主上下文中查找它时,却没有找到。主要背景does包含该实体 - 我可以记录其详细信息并确认它在那里 - 但地址不同?如果这是注定要发生的(为什么?),我如何在保存后在主上下文中找到添加的对象?
感谢您的任何见解。很抱歉问了一个很长、由多个部分组成的问题,但我认为以前可能有人已经解决了所有这些问题。
父/子 MOC 模型是 Core Data 的一个非常强大的功能。它极大地简化了我们过去必须处理的古老并发问题。但是,正如您所说,并发不是您的问题。回答您的问题:
- 传统上,您使用
NSMainQueueConcurrencyType
为了NSManagedObjectContext
与主线程相关联,以及NSPrivateQueueConcurrencyType
s 用于子上下文。子上下文不需要与其父上下文匹配。这NSConfinementConcurrencyType
就是全部NSManagedObjectContext
如果您不指定类型,则默认为 s。它基本上是“我将管理自己的核心数据线程”类型。
- 在没有看到您的代码的情况下,我的假设是您创建子上下文的范围结束并被清理。
- 当使用父/子上下文模式时,您需要使用块方法。使用块方法的最大好处是操作系统将处理将方法调用分派到正确的线程。您可以使用
performBlock
对于异步执行,或者performBlockAndWait
用于同步执行。
您可以使用它,例如:
- (void)saveContexts {
[childContext performBlock:^{
NSError *childError = nil;
if ([childContext save:&childError]) {
[parentContext performBlock:^{
NSError *parentError = nil;
if (![parentContext save:&parentError]) {
NSLog(@"Error saving parent");
}
}];
} else {
NSLog(@"Error saving child");
}
}];
}
现在,您需要记住,在保存之前,在子上下文中所做的更改(例如插入的实体)将无法用于父上下文。对于子上下文来说,父上下文是持久存储。保存时,您将这些更改传递给父级,然后父级可以将它们保存到实际的持久存储中。将传播更改保存到上一级。另一方面,获取子上下文将通过每个级别向下拉数据(通过父级并进入子级)
- 你需要使用某种形式
objectWithID
在 ManagedObjectContext 上。它们是在上下文之间传递对象的最安全(也是唯一)的方法。正如汤姆·哈林顿在评论中提到的,你可能想使用existingObjectWithID:error:
虽然因为objectWithID:
始终返回一个对象,即使您传入无效 ID(这可能导致异常)。更多细节:Link https://stackoverflow.com/questions/4818526/whats-the-proper-way-to-use-nsmanagedobjectcontexts-objectwithid
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)