在并发NSOperation中使用MagicalRecord的正确方法(MagicalRecord-2.3)

时间:2014-04-10 23:54:23

标签: magicalrecord

由于MR_contextForCurrentThread对操作不安全(并且已被弃用),我试图确保我理解并发操作中一系列读/写的最佳模式。

建议使用saveWithBlock来存储新记录,并且可能是删除,它提供了使用的上下文。 Count和fetch方法可以给出一个上下文,但默认情况下仍然使用MR_contextForCurrentThread。

最安全的模式是在操作开始时使用[NSManagedObjectContext MR_context]获取上下文,并将其用于所有操作。该操作取决于某些异步工作,但不会长时间运行。然后在操作完成后执行MR_saveToPersistentStoreWithCompletion?

2 个答案:

答案 0 :(得分:2)

使用NSOperation的原因是什么?这里有两个选择:

使用MagicalRecord的后台保存块:

[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
    // Do your task for the background thread here
}];

另一个选项是(正如您已经尝试过的)将其捆绑到NSOperation中。是的,我会使用[NSManagedObjectContext MR_newContext]缓存一个私有队列上下文的实例(抱歉,我今天下午弃用了MR_context方法,转而采用更清晰的替代方法)。请注意,除非您手动合并来自其他上下文的更改,否则您创建的专用队列上下文将是您创建它时的父上下文的快照。通常,这对于短期运行的后台任务来说不是问题。

托管对象上下文非常轻巧且便宜 - 只要您要在主线程以外的任何线程上工作,只需初始化并使用新上下文。它让事情变得简单。就个人而言,我赞成+ saveWithBlock:及相关方法 - 它们很简单。

希望有所帮助!

答案 1 :(得分:1)

如果您愿意,则无​​法使用多个线程中的saveWithBlock(并发NSOperations):

  • 依靠Magical Record的主要属性功能创建
  • 依赖于自动建立关系(依赖于主要属性)
  • 手动获取/ MR_find对象并根据其结果进行保存

这是因为无论何时使用saveWithBlock创建新的本地上下文,都会在同一时间创建多个上下文,并且他们不知道彼此之间的更改。正如Tony提到的那样localContextrootContext的快照,更改仅在一个方向上进行,从localContextrootContext,但反之亦然。

这是一种同步调用saveWithBlock的线程保存(甚至是MagicalRecord的一致性安全)方法:

@implementation MagicalRecord (MyActions)
+ (void) my_saveWithBlock:(void(^)(NSManagedObjectContext *localContext))block completion:(MRSaveCompletionHandler)completion;
{
    static dispatch_semaphore_t semaphore;
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        semaphore = dispatch_semaphore_create(1);
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        [MagicalRecord saveWithBlock:block
            completion:^(BOOL success, NSError *error) {
                dispatch_semaphore_signal(semaphore);
                if (completion){
                    completion(success, error);
                }
            }];
    });
}
@end