2

我试图找到这个问题的答案,但我无法从文档和 StackOverflow 中找出问题。如果已经有这样的问题,我只是没有找到它,所以它会非常欢迎作为以防万一的解决方案。

我的情况是:我有两个核心数据实体,一个用户和一个驾驶执照。

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];

会引起一些混乱,最终将驾驶执照删除吗?或者还有什么可能是这个意外的空值的原因?

4

2 回答 2

2

当您使用 MR_createEntity 时,您会隐式使用默认上下文,通过[NSManagedObjectContext MR_defaultContext]访问。除非您绝对积极地从主线程调用它,否则这样做是非常危险的。在您的示例中,如果从主线程调用所有内容并且您的self.managedObjectContext实例变量也指向默认上下文,则所有这些都应该正常工作。否则,您将需要明确说明您正在使用哪些上下文。MagicalRecord 通过在每个需要上下文才能工作的方法末尾添加一个 inContext: 可选参数来为您提供这些约定。查看MR_createInContext:方法并明确使用上下文

于 2012-11-13T17:27:12.997 回答
0

刚好碰到这个问题。根据我们的发现,我想在上面casademora的回答中添加一些评论:

重要的要记住核心数据以及任何MR_save方法都不是线程安全的。我们将 MagicalRecord 操作委托给队列以解决此问题。MR_saveToPersistentStoreAndWait具体来说,重要的是要记住不要同时在多个线程中执行保存操作(例如)。

然而MR_createEntityMR_defaultContext、 和Main线程之间的联系更加微妙。从 MagicalRecord 版本 2.3.x 开始,我不相信MR_createEntity没有参数的 . 默认为MR_defaultContext. 我相信它默认为MR_contextForCurrentThread. MR_contextForCurrentThread如果它在线程上,则返回默认上下文,否则不返回。如果您不了解后果,这是很危险的,因为您可以很容易地看到原始海报在上面看到的内容(丢失的数据)。

事实上,这个注释表明你应该使用MR_createEntityInContext:localContext而不是MR_createEntity因为使用MR_contextForCurrentThread时出现问题GCD

有关使用的逻辑,请参见github 中的函数定义MR_createEntityMR_contextForCurrentThread

于 2016-05-21T23:46:27.123 回答