我的多线程 Core Data 应用程序一直有问题,我想我应该认真看看我在做什么以及如何做。请让我知道以下是否可行。
我有一个DataManager
处理核心数据的单例类。它具有managedObjectContext
为每个线程返回不同 MOC 的属性。因此,给定NSMutableDictionary *_threadContextDict
(字符串线程名称到上下文)和NSMutableDictionary *_threadDict
(字符串线程名称到线程),它看起来像这样:
-(NSManagedObjectContext *)managedObjectContext
{
if ([NSThread currentThread] == [NSThread mainThread])
{
MyAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
return delegate.managedObjectContext; //MOC created in delegate code on main thread
}
else
{
NSString *thisThread = [[NSThread currentThread] description];
{
if ([_threadContextDict objectForKey:thisThread] != nil)
{
return [_threadContextDict objectForKey:thisThread];
}
else
{
NSManagedObjectContext *context = [[NSManagedObjectContext alloc]init];
MyAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[context setPersistentStoreCoordinator:delegate.persistentStoreCoordinator];
[_threadContextDict setObject:context forKey:thisThread];
[_threadDict setObject:[NSThread currentThread] forKey:thisThread];
//merge changes notifications
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(mergeChanges:)
name:NSManagedObjectContextDidSaveNotification object:context];
return context;
}
}
}
}
在该mergeChanges
方法中,我将来自传入通知的更改合并到除生成通知的上下文之外的所有上下文。它看起来像这样:
-(void)mergeChanges:(NSNotification *)notification
{
MyAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = delegate.managedObjectContext;
[context performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification)
withObject:notification waitUntilDone:YES];
for (NSString *element in [_threadContextDict allKeys])
{
if (![element isEqualToString:[[NSThread currentThread] description]])
{
NSThread *thread = [_threadDict objectForKey:element];
NSManagedObjectContext *threadContext = [_threadContextDict objectForKey:element];
[threadContext performSelector:@selector(mergeChangesFromContextDidSaveNotification)
onThread:thread withObject:notification waitUntilDone:YES];
}
}
}
每当我在 MOC 上保存更改时,都是通过调用saveContext
此 shared 上的方法来完成的,该方法DataManager
调用save
从上述属性获得的上下文:
-(void)saveContext
{
NSManagedObjectContext *context = self.managedObjectContext;
NSError *err = nil;
[context save:&err];
//report error if necessary, etc.
}
鉴于我对 Core Data 多线程规则的理解,我觉得这应该可行。我为每个线程使用单独的上下文,但对所有线程使用相同的持久存储。但是当我使用它时,我会遇到很多合并冲突,即使我的线程没有处理相同的对象(NSManagedObject
子类)。我只是从网络上下载数据,解析结果,然后将它们保存到 Core Data。
难道我做错了什么?我试过使用NSLock
实例来锁定一些东西,但后来我就挂了。
更新/解决方案:我可以通过添加一个简单的东西来完成这项工作:一种在我完成后从我的字典中删除线程/MOC 对的方法。在每次调用dispatch_async
我做核心数据的地方的每个块的末尾,我调用[self removeThread]
,它从字典中删除当前线程及其 MOC。我也只合并对主线程 MOC 的更改。实际上,这意味着每次我在后台线程上工作时,我都会得到一个全新的 MOC。
我还通过添加一个数字来区分线程userInfoDict
,而不是调用description
. 该数字是通过我的类上的只读属性获得的,该属性每次调用时都会返回一个更高的数字。