在我的App中,我使用JSON内容获取请求,解析它们并将它们存储在CoreData中。在用户与DB交互的同时(读写访问)。
将数据存储到数据库后,将启动第二个任务,根据接收的数据创建新数据。我将使用Grand Central Dispatch进行解析并将数据存储到数据库中。
我的问题是,当使用GCD时,我得到一个EXC_BAD_ACCESS
,这可能是由于我假设的Core Data的非线程安全性造成的。另一个错误是我在使用上下文performBlockAndWait
时遇到了死锁。
我应该如何设计正确处理GCD和NSMutableContexts
的应用?
------- -------- EDIT
现在我已经阅读了核心数据编程指南,我发现我必须使用线程限制模式。
我的应用程序目前以这种方式构建:我有几个管理器,每个管理器都拥有自己的上下文。但是当使用多个线程时,我发现3个线程调用同一个Manager,这意味着3个线程同时使用一个上下文。这会导致死锁。
为了解决这个问题,我想到了通过threadname创建一个上下文:
- (NSManagedObjectContext *)createManagedObjectContextWithTreadName:(NSString*) threadname {
if([NSThread currentThread].name.length ==0){
[NSThread currentThread].name = threadname;
}
NSManagedObjectContext *context = nil;
context = [self.contextStore objectForKey:threadname];
if(!context){
NSLog(@"Creating context for threadname: %@",threadname);
NSPersistentStoreCoordinator *coordinator = self.persistentStoreCoordinator;
if (coordinator != nil)
{
context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
context.persistentStoreCoordinator = coordinator;
context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(mergeChangesFromMOC:) name:NSManagedObjectContextDidSaveNotification object:context];
[self.contextStore setValue:context forKey:threadname];
}
}
return context;
}
这是个好主意吗?
答案 0 :(得分:3)
答案 1 :(得分:2)
好的 - 这就是我解决它的方法:
+(NSManagedObjectContext *)managedObjectContext {
AppDelegate *delegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
NSManagedObjectContext *moc = delegate.managedObjectContext;
NSThread *thread = [NSThread currentThread];
if ([thread isMainThread]) {
return moc;
}
// a key to cache the context for the given thread
NSString *threadKey = [NSString stringWithFormat:@"%p", thread];
// delegate.managedObjectContexts is a mutable dictionary in the app delegate
NSMutableDictionary *managedObjectContexts = delegate.managedObjectContexts;
if ( [managedObjectContexts objectForKey:threadKey] == nil ) {
// create a context for this thread
NSManagedObjectContext *threadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
threadContext.persistentStoreCoordinator = [moc persistentStoreCoordinator];
threadContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(mergeChangesFromMOC:) name:NSManagedObjectContextDidSaveNotification object:threadContext];
// cache the context for this thread
[managedObjectContexts setObject:threadContext forKey:threadKey];
//NSLog(@"MocCount: %d",managedObjectContexts.count);
}
return [managedObjectContexts objectForKey:threadKey];
}
+ (void)mergeChangesFromMOC:(NSNotification *)aNotification {
//NSLog(@"Performing a merge of managed object context in class %@",[self class]);
@try {
AppDelegate *delegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
NSManagedObjectContext *moc = delegate.managedObjectContext;
[moc mergeChangesFromContextDidSaveNotification:aNotification];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc removeObserver:self name:NSManagedObjectContextDidSaveNotification object:[aNotification object]];
}
@catch (NSException * e) {
NSLog(@"Stopping on exception: %@", [e description]);
}
@finally {}
}
我需要一个上下文,我问[ContainingClass managedObjectContext]并获取主线程或我所在线程的上下文。当需要合并时,这将在主线程上执行。