我知道有很多关于NSManagedObjectContexts和线程的线程,但我的问题似乎只针对iOS7。 (或者至少在OS6中不可见)
我有一个使用dispatch_queue_的应用程序,并运行多个线程从服务器获取数据并更新UI。该应用程序在iOS6上工作正常但在iOS7上它似乎陷入死锁(互斥等待)。请参阅下面的堆栈跟踪 -
“等待”通常在执行获取请求和保存(不同)上下文时以不同的方式发生。提交方法如下:
-(void)commit:(BOOL) shouldUndoIfError forMoc:(NSManagedObjectContext*)moc {
@try {
// shouldUndoIfError = NO;
// get the moc for this thread
NSManagedObjectContext *moc = [self safeManagedObjectContext];
NSThread *thread = [NSThread currentThread];
NSLog(@"got login");
if ([thread isMainThread] == NO) {
// only observe notifications other than the main thread
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:moc];
NSLog(@"not main thread");
}
NSError *error;
if (![moc save:&error]) {
// fail
NSLog(@"ERROR: SAVE OPERATION FAILED %@", error);
if(shouldUndoIfError) {
[moc undo];
}
}
if ([thread isMainThread] == NO) {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSManagedObjectContextDidSaveNotification
object:moc];
}
}
@catch (NSException *exception) {
NSLog(@"Store commit - %@",exception);
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"name",@"store commit",@"exception", exception.description, nil];
[Flurry logEvent:@"MyException" withParameters:dictionary timed:YES];
}
@finally {
NSLog(@"Store saved");
}
}
我如何为每个帖子创建新的上下文:
-(NSManagedObjectContext *)safeManagedObjectContext {
@try {
if(self.managedObjectContexts == nil){
NSMutableDictionary *_dict = [[NSMutableDictionary alloc]init];
self.managedObjectContexts = _dict;
[_dict release];
_dict = nil;
}
NSManagedObjectContext *moc = self.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];
if ( [self.managedObjectContexts valueForKey:threadKey] == nil) {
// create a context for this thread
NSManagedObjectContext *threadContext = [[[NSManagedObjectContext alloc] init] retain];
[threadContext setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];
[threadContext setPersistentStoreCoordinator:[moc persistentStoreCoordinator]];
[threadContext setUndoManager:nil];
// cache the context for this thread
[self.managedObjectContexts setObject:threadContext forKey:threadKey];
NSLog(@"added a context to dictionary, length is %d",[self.managedObjectContexts count]);
}
return [self.managedObjectContexts objectForKey:threadKey];
}
@catch (NSException *exception) {
//
}
@finally {
//
}
}
到目前为止我所拥有的:
奇怪的是,相同的代码在OS6上运行良好,但在OS7上运行不正常。我仍在使用xcode4.6.3来编译代码。大多数代码都遵循这个原则,我运行一个线程,获取数据,提交它然后发布通知。冻结/死锁是否因为通知被发布而我的UI元素在反映保存(& merge)之前获取数据?我还缺少什么?