eve*_*ive 5 core-data nsfetchedresultscontroller nsnotificationcenter nsmanagedobjectcontext ios
使用,当我遇到有趣的行为来的NSManagedObjectContext的performBlock:
与通知中心.
从主UI线程我触发异步数据下载(使用NSURLConnection的connectionWithRequest:
).当数据到达时,将调用以下委托方法:
- (void)downloadCompleted:(NSData *)data
{
NSArray *new_data = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
self.backgroundObjectContext = [[NSManagedObjectContext alloc]
initWithConcurrencyType:NSPrivateQueueConcurrencyType];
self.backgroundObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator;
[self.backgroundObjectContext performBlockAndWait:^{
[self saveToCoreData:new_data];
}];
}
Run Code Online (Sandbox Code Playgroud)
该savetoCoreData:
方法只是将新数据保存到后台上下文:
- (void)saveToCoreData:(NSArray*)questionsArray
{
for (NSDictionary *questionDictionaryObject in questionsArray) {
Question *newQuestion = [NSEntityDescription
insertNewObjectForEntityForName:@"Question"
inManagedObjectContext:self.backgroundObjectContext];
newQuestion.content = [questionDictionaryObject objectForKey:@"content"];
}
NSError *savingError = nil;
[self.backgroundObjectContext save:&savingError];
}
Run Code Online (Sandbox Code Playgroud)
在视图控制器中,viewDidLoad
我将观察者添加到通知中心:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextChanged:)
name:NSManagedObjectContextDidSaveNotification
object:nil];
Run Code Online (Sandbox Code Playgroud)
然后在contexChanged:
我合并背景上下文与主上下文,以便调用我的NSFetchedResultsController的委托方法,我的视图可以更新:
- (void)contextChanged:(NSNotification*)notification
{
if ([notification object] == self.managedObjectContext) return;
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}
Run Code Online (Sandbox Code Playgroud)
这一切似乎运作良好,但有一件事困扰着我.在downloadCompleted:
方法中我使用performBlock:
而不是performBlockAndWait:
通知似乎被延迟.从后台线程save:
到NSFetchedResultsController调用其委托的那一刻起,它需要花费很多时间(大约5s).当我使用时,performBlockAndWait:
我没有观察到任何可见的延迟 - 代表的调用速度就像我saveToCoreData:
在里面调用一样快_dispatch_async_
.
有没有人以前看过,知道这是正常还是我滥用了什么?
正如 Dan 在评论之一中指出的那样,合并操作应该发生在主线程上。contextChanged:
通过更改方法来执行以下操作可以轻松观察到这一点:
- (void)contextChanged:(NSNotification*)notification\n{\n if ([notification object] == self.managedObjectContext) return;\n\n if (![NSThread isMainThread]) {\n [self performSelectorOnMainThread:@selector(contextChanged:) \n withObject:notification \n waitUntilDone:YES];\n return;\n }\n\n [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n随着这一变化, 和performBlock:
都performBlockAndWait:
开始发挥作用。
只要这在某种程度上解释了问题首先发生的原因,我仍然不明白为什么performBlock:
并且performBlockAndWait:
从线程的角度执行不同的操作。苹果文档说:
\n\n\n\n
performBlock:
并performBlockAndWait:
确保块操作在为上下文指定的队列上执行。该performBlock:
方法立即返回,上下文在其自己的线程上执行块方法。使用该performBlockAndWait:
方法,上下文仍然在其自己的线程上执行块方法,但在执行块之前该方法不会返回。
这表明,如果问题中描述的问题的真正根本原因是合并发生在后台线程中,那么无论我调用哪个方法,我都应该观察到相同的行为:performBlock:
并且performBlockAndWait:
- 两者都在单独的线程中执行。
作为旁注,由于在NSURLConnection
启动异步加载操作的同一线程(在我的例子中是主线程)上调用委托方法,因此使用后台上下文似乎根本没有必要。NSURLConnections
无论如何,在运行循环中传递其事件。
归档时间: |
|
查看次数: |
3271 次 |
最近记录: |