CoreData + MagicalRecord - 我是否正确保存了详细信息?

时间:2013-12-24 17:12:39

标签: cocoa core-data magicalrecord

我的数据库中有三个Applications。我有一个删除一个谓词。

给出以下代码:

[Application MR_deleteAllMatchingPredicate: applicationDeletePredicate];
[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];

NSLog(@"We have %ld apps left.", [Application MR_countOfEntities]);

dispatch_async(dispatch_get_main_queue(), ^{
    NSLog(@"We have %ld apps left.", [Application MR_countOfEntities]);
});

我收到以下日志消息:

We have 2 apps left.

We have 3 apps left.

所以它已经正确删除了谓词,但是当我尝试在主队列中重新加载时,应用程序仍然存在。我做错了吗?在处理MagicalRecord时(在我的计数方法中)我是否应该始终指定默认上下文?

1 个答案:

答案 0 :(得分:11)

尽管MagicalRecord确实提供了减少打字的方法,但您需要了解幕后发生的事情,以避免出现类似情况。

特别是,您需要了解MagicalRecord何时创建新的上下文以及如何配置它们。

MagicalRecord为需要上下文的操作提供方法,但这些方法不将上下文作为参数。在这些情况下,MagicalRecord使用[NSManagedObjectContext MR_contextForCurrentThread]方法来获取默认上下文或创建一个新的上下文,该上下文是默认上下文的子项。如果它创建了一个新的上下文,它会为当前线程缓存它以供以后重用(考虑到Apple使用队列并发类型的上下文的方向,当你使用块内的对象时,这是一个不好的做法。)

但长话短说,这里可能会发生什么。

  1. 您提供的代码在后台线程上运行。
  2. [Application MR_deleteAllMatchingPredicate: applicationDeletePredicate];创建一个新的上下文,它是默认上下文的子项,并执行删除。
  3. [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];(从主线程非法调用,考虑到1.顺便说一下)保存了不知道删除的默认上下文,因为从未保存子上下文并且没有推送更改到父,默认,上下文。
  4. 第一个NSLog中的
  5. [Application MR_countOfEntities]在与删除相同的上下文中运行并返回新计数。
  6. 第二个NSLog中的
  7. [Application MR_countOfEntities]在主队列上运行。因为它在主线程上运行,所以它使用默认上下文,从未看到过这个删除,因为child从未保存过。所以它返回旧计数。
  8. 您需要做的是确保保存子上下文及其所有父项。因此,您可能需要将第二行中的默认上下文替换为当前线程的上下文:[[NSManagedObjectContext MR_contextForCurrentThread] MR_saveToPersistentStoreAndWait];

    但我会避免隐藏的上下文创建,并会明确地创建它们。所以我的第一个建议是避免使用不将上下文作为参数的MagicalRecord方法(当有相似的方法时)。

    我的第二个建议是不使用MagicalRecord,而是直接使用Core Data。首先,您可以使用全局使用的两个上下文:一个具有主队列并发类型的上下文,您将在主线程上使用它来更新UI。另一个具有私有队列并发类型的用户,可用于所有后台任务,并配置为主要上下文的子级。