【发布时间】:2012-09-17 20:43:54
【问题描述】:
我的多线程 Core Data 应用程序一直在使用 problems,我想我应该认真看看我在做什么以及如何做。请让我知道以下是否可行。
我有一个单独的 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 上保存更改时,都是通过调用此共享 DataManager 上的 saveContext 方法来完成的,该方法在从上述属性获得的上下文中调用 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。该数字是通过我的类上的只读属性获得的,每次调用它时都会返回一个更高的数字。
【问题讨论】:
-
您接受了一个答案,但您能解决您的问题吗?你做了什么?
标签: objective-c multithreading core-data grand-central-dispatch nsmanagedobjectcontext