我在登录私有上下文后正在做一些繁重的核心数据插入工作(比如 A)(以避免主线程阻塞)。不幸的是,在完成此操作之前,不幸的是,在代码中的某个地方也有一个插入工作(例如 B)(不重),但是必不可少的,并且还使用私有上下文来保存。
问题:在将记录保存在任何地方时,我检查它们是否已在数据库中(以确保唯一记录),但是在上述任务完成后,我检查coredata,我发现一些记录重复,这仅仅是由于在我调用"保存"之前在任务A,另一个进程B已经写入了重复记录。
我正在寻找解决方案,预见两种选择:
- 让第二个任务等待第一个任务(在另一个线程中调度并等待直到完成)
- 请推荐!!
编辑:事实证明,问题更多地与合并而不是并发有关,合并会产生重复记录,并发性很好,抛出的错误是:
NSCocoaErrorDomain Code=133020
更新:已使用覆盖合并策略修复合并问题
您在问题中自己说过,您的对象正在复制,因为您是从两个不同的位置保存的。
一种策略是使用相同的 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
尽管如此,您可以通过多种方式定义接口,但重要的是您有一个处理核心数据读取和写入的接口。