0

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

问题:在将记录保存在任何地方时,我检查它们是否已经在数据库中(以确保唯一的记录),但是在完成上述任务并检查 coredata 后,我发现一些记录重复,这仅仅是因为在我打电话之前在任务 A 处“保存”,另一个进程 B 已经写入了重复记录。

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

  1. 让第二个任务等待第一个任务(在另一个线程中调度并等待直到完成)
  2. 请推荐!!

编辑: 事实证明,问题更多地与合并而不是并发有关,合并创建重复记录,并发很好,抛出的错误是:

NSCocoaErrorDomain Code=133020

更新: 合并问题已通过覆盖合并策略修复

4

1 回答 1

1

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

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

话虽如此,您恰好处于您的两个写入操作可能写入同一个对象的位置。我将通过单个接口管理所有写入,然后该接口将保留用于写入的私有上下文。由于上下文是一个串行队列,您可以保证您不能两次写入同一个对象(假设您的重复检查是坚如磐石的)。

所以你的界面可能是这样的:

@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

尽管如此,您可以通过多种方式定义接口,但重要的是您有一个处理核心数据读取和写入的接口。

于 2014-11-13T12:28:56.700 回答