Ios 父/子NSManagedObjectContext的正确实现
我的应用程序有时会将不一定要保存的对象插入到托管对象上下文中。例如,当我启动“添加实体”模式时,我创建一个托管对象并将其分配给该模式。如果用户从该模式保存,则我保存上下文。如果他取消,我将删除该对象,无需保存 我现在引入了一个“导入”功能,可以切换到我的应用程序(使用URL方案)并添加一个实体。因为其中一个模态可能是打开的,所以此时保存上下文是不安全的。即使用户取消,为模式创建的临时对象也将被保存,并且不能保证删除(从取消操作)将在以后保存-用户可能会退出应用程序 同样,我不能在我的应用程序退出时简单地保存。如果模态在该点打开,则临时对象将被错误保存 为了解决这个问题,我尝试使用一个子上下文,正如前面所讨论的。在阅读了所有关于SO的资料后,我有几个问题:Ios 父/子NSManagedObjectContext的正确实现,ios,objective-c,cocoa,core-data,nsmanagedobjectcontext,Ios,Objective C,Cocoa,Core Data,Nsmanagedobjectcontext,我的应用程序有时会将不一定要保存的对象插入到托管对象上下文中。例如,当我启动“添加实体”模式时,我创建一个托管对象并将其分配给该模式。如果用户从该模式保存,则我保存上下文。如果他取消,我将删除该对象,无需保存 我现在引入了一个“导入”功能,可以切换到我的应用程序(使用URL方案)并添加一个实体。因为其中一个模态可能是打开的,所以此时保存上下文是不安全的。即使用户取消,为模式创建的临时对象也将被保存,并且不能保证删除(从取消操作)将在以后保存-用户可能会退出应用程序 同样,我不能在我的应用程序退出
//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");}
}];
NSMainQueueConcurrencyType
声明父上下文,使用NSPrivateQueueConcurrencyType
声明子上下文NSConfinementConcurrencyType
用于经典线程模式-objectRegisteredForID:
-objectWithID:
-existingObjectWithID:错误:
我也遇到过类似的问题,下面是对你的一些问题的回答- 1.您应该能够使用并发类型
NSPrivateQueueConcurrencyType
或NSMainQueueConcurrencyType
2.假设您已经使用父上下文mainContext
创建了一个临时上下文tempContext
(假设为iOS5)。在这种情况下,您只需将托管对象从tempContext
移动到mainContext
-
object = (Object *)[mainContext objectWithID:object.objectID];
然后可以保存mainContext本身
也许也
[childContext reset];
如果您想重置临时上下文。父/子MOC模型是核心数据非常强大的功能。它极大地简化了我们过去必须处理的古老的并发问题。然而,正如您所说的,并发性不是您的问题。回答您的问题:
NSManagedObjectContext
使用NSMainQueueConcurrencyType
,对于子上下文使用NSPrivateQueueConcurrencyType
s。子上下文不需要与其父上下文匹配。如果不指定类型,则所有NSManagedObjectContext
都会默认使用NSConfinementConcurrencyType
。它基本上是“我将为核心数据管理自己的线程”类型performBlock
进行异步执行,也可以使用performBlock和wait
进行同步执行- (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");
}
}];
}
现在,您需要记住,在保存之前,在子上下文中所做的更改(例如插入的实体)将不可用于父上下文。对于子上下文,父上下文是持久存储。保存时,将这些更改传递给父级,然后父级可以将它们保存到实际的持久存储中。保存propogate