我在登录私有上下文之后做了一些繁重的核心数据插入工作(比如A)(以避免主线程封锁)。 在此之前,不幸的是在代码的某个地方还有一个插入工作(比如B)(不重)但是必不可少,并且还使用私有上下文来保存。
ISSUE:在保存记录的任何地方我检查它们是否已经在DB中(以确保唯一记录),但在上述任务完成后我检查coredata我发现一些记录重复,在我在任务A中调用'save'之前,其他进程B已经编写了重复记录。
我正在寻找解决方案,预见两种选择:
修改 事实证明,问题更多地与合并而不是并发相关,合并会创建重复记录,并发性很好,抛出的错误是:
NSCocoaErrorDomain Code=133020
更新 使用覆盖合并策略修复合并问题
答案 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读写的接口。