核心数据并发:避免在两个单独的地方写作

时间:2014-11-13 08:20:17

标签: ios core-data ios7 nsmanagedobjectcontext nscondition

我在登录私有上下文之后做了一些繁重的核心数据插入工作(比如A)(以避免主线程封锁)。 在此之前,不幸的是在代码的某个地方还有一个插入工作(比如B)(不重)但是必不可少,并且还使用私有上下文来保存。

ISSUE:在保存记录的任何地方我检查它们是否已经在DB中(以确保唯一记录),但在上述任务完成后我检查coredata我发现一些记录重复,在我在任务A中调用'save'之前,其他进程B已经编写了重复记录。

我正在寻找解决方案,预见两种选择:

  1. 让第二个任务等待第一个任务(在另一个线程中调度并等待直到完成)
  2. plz推荐!!
  3. 修改 事实证明,问题更多地与合并而不是并发相关,合并会创建重复记录,并发性很好,抛出的错误是:

    NSCocoaErrorDomain Code=133020
    

    更新 使用覆盖合并策略修复合并问题

1 个答案:

答案 0 :(得分:1)

你自己在问题中说过,你的对象是重复的,因为你是从两个不同的位置保存的。

一种策略是使用相同的NSManagedObjectContext执行所有写入操作。很少需要创建多个背景上下文来执行写入(除非您的写入花费很长时间)。

说得清楚的是,你碰巧处于两个Write操作可能写入同一个对象的位置。我将通过单个接口管理所有写入,然后此接口将保留用于写入的私有上下文。由于上下文是一个串行队列,因此您可以保证您无法两次写入相同的对象(假设您检查重复是坚如磐石的。)

所以你的界面可能如下所示:

@interface CoreDataManager : NSObject
+ (CoreDataManager*)sharedManager;
- (void)performWriteWithBlock:(void (^)(NSManagedObjectContext *writeContext))writeBlock;
@end

@implementation CoreDataManager
+ (CoreDataManager *)sharedManager {
    static dispatch_once_t once;
    dispatch_once(&once, ^ {
        self.writeContext = [[self class] createBackgroundPersistanceObjectContext];
    });
    return sharedManager;
}

- (void)performWriteWithBlock:(void (^)(NSManagedObjectContext *writeContext))writeBlock {
    if (writeBlock) {
        writeBlock(self.writeContext);
        [self.writeContext save:nil];
    }
}

+ (NSManagedObjectContext *)createBackgroundPersistanceObjectContext {
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [context setPersistentStoreCoordinator:coordinator];
    context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;
    context.undoManager = nil;
    return context;
}
@end

尽管如此,您可以通过多种方式定义接口,但重要的是您有一个处理Core Data读写的接口。