核心数据合并行为
Posted
技术标签:
【中文标题】核心数据合并行为【英文标题】:Core Data merge behaviour 【发布时间】:2012-11-13 11:58:58 【问题描述】:我试图找到这个问题的答案,但我无法从文档和 *** 中找出问题。如果已经有这样的问题,我只是没有找到它,所以它会非常欢迎作为以防万一的解决方案。
我的情况是: 我有两个核心数据实体,一个用户和一个驾驶执照。
User <--- 1 to 1 ---> Driving Licence
我使用Magical Record 作为核心数据操作的抽象层。
我的用户类(从 NSManagedObject 派生)公开了 2 个方法。
一个访问用户的单例实例(整个应用程序中唯一使用的一个):
+ (User *)currentUser
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
if ([User MR_findFirst] == nil)
User *user = [User MR_createEntity];
user.drivingLicence = [DrivingLicence MR_createEntity];
[[user managedObjectContext] MR_save];
);
return [User MR_findFirst];
还有一个用来重置用户数据的方法(来源于NSManagedObject):
- (void)resetFields
self.name = nil;
self.surname = nil;
....
[self.drivingLicence MR_deleteEntity];
self.drivingLicence = [DrivingLicence MR_createEntity];
[self.managedObjectContext MR_save];
有时,我会很随意地说,drivingLicence 字段恰好为空。 可能会有后台线程调用 resetFields 方法的情况。
难道是为了与其他上下文合并,指令序列
[self.drivingLicence MR_deleteEntity];
self.drivingLicence = [DrivingLicence MR_createEntity];
会导致一些混乱,导致驾驶执照最终被删除? 或者这个意外的空值还有什么原因?
【问题讨论】:
【参考方案1】:当您使用 MR_createEntity 时,您会隐式使用默认上下文,通过 [NSManagedObjectContext MR_defaultContext] 访问。除非您绝对积极地从主线程调用它,否则这样做是非常危险的。在您的示例中,如果从主线程调用所有内容并且您的 self.managedObjectContext 实例变量也指向默认上下文,则所有这些都应该正常工作。否则,您将需要明确说明您正在使用哪些上下文。 MagicalRecord 通过在每个需要上下文才能工作的方法末尾添加一个 inContext: 可选参数来为您提供这些约定。查看 MR_createInContext: 方法并明确使用上下文
【讨论】:
【参考方案2】:刚刚遇到这个问题。根据我们的发现,我想在上面casademora 的答案中添加一些 cmets:
重要的是要记住核心数据以及任何MR_save
方法都不是线程安全的。我们将 MagicalRecord 操作委托给队列以解决此问题。具体来说,重要的是要记住不要同时在多个线程中执行保存操作(例如MR_saveToPersistentStoreAndWait
)。
但是MR_createEntity
、MR_defaultContext
和 Main 线程之间的联系更加微妙。从 MagicalRecord 版本 2.3.x 开始,我不相信 MR_createEntity
,没有参数,默认为 MR_defaultContext
。我相信它默认为MR_contextForCurrentThread
。 MR_contextForCurrentThread
如果它在 Main 线程上,则返回默认上下文,否则不返回。如果您不了解后果,这是很危险的,因为您可以很容易地看到原始海报在上面看到的内容(丢失的数据)。
其实this note表示你应该使用MR_createEntityInContext:localContext
而不是MR_createEntity
,因为使用GCD
时MR_contextForCurrentThread
有问题。
请参阅 github 中的 the function definition,了解 MR_createEntity
使用 MR_contextForCurrentThread
的逻辑。
【讨论】:
以上是关于核心数据合并行为的主要内容,如果未能解决你的问题,请参考以下文章