gpt4 book ai didi

ios - NSManagedObjectContext:带有通知中心的 performBlockAndWait 与 performBlock

转载 作者:可可西里 更新时间:2023-11-01 04:46:48 26 4
gpt4 key购买 nike

在将 NSManagedObjectContextperformBlock: 与通知中心一起使用时,我遇到了有趣的行为。

我从主 UI 线程触发异步数据下载(使用 NSURLConnectionconnectionWithRequest:)。当数据到达时调用以下委托(delegate)方法:

- (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];
}];
}

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];
}

在 View Controller 中,在 viewDidLoad 中,我将观察者添加到通知中心:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextChanged:) 
name:NSManagedObjectContextDidSaveNotification
object:nil];

然后在 contexChanged: 中,我将背景上下文与主上下文合并,以便在可以更新 View 的地方调用 NSFetchedResultsController 的委托(delegate)方法:

- (void)contextChanged:(NSNotification*)notification
{
if ([notification object] == self.managedObjectContext) return;

[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}

这一切似乎都很好,但有一件事困扰着我。在 downloadCompleted: 方法中我使用 performBlock: 而不是 performBlockAndWait: 时,通知似乎被延迟了。从后台线程执行 save:NSFetchedResultsController 调用其委托(delegate)需要很长时间(大约 5 秒)。当我使用 performBlockAndWait: 时,我没有观察到任何可见的延迟 - 委托(delegate)的调用速度与我在 _dispatch_async_ 中调用 saveToCoreData: 一样快。

有没有人以前看过并知道这是正常现象还是我在滥用某些东西?

最佳答案

正如 Dan 在其中一条评论中所指出的,合并操作应该发生在主线程上。通过更改 contextChanged: 方法来执行以下操作,可以很容易地观察到这一点:

 - (void)contextChanged:(NSNotification*)notification
{
if ([notification object] == self.managedObjectContext) return;

if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(contextChanged:)
withObject:notification
waitUntilDone:YES];
return;
}

[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}

通过此更改,performBlock:performBlockAndWait: 都可以正常工作。

只要这在一定程度上解释了为什么首先会出现问题,我仍然不明白为什么 performBlock:performBlockAndWait: 的表现与线程的观点。苹果文档说:

performBlock: and performBlockAndWait: ensure the block operations are executed on the queue specified for the context. The performBlock: method returns immediately and the context executes the block methods on its own thread. With the performBlockAndWait: method, the context still executes the block methods on its own thread, but the method doesn’t return until the block is executed.

这表明,如果问题中描述的问题的真正根本原因是合并发生在后台线程中,那么无论我调用哪种方法,我都应该观察到相同的行为:performBlock:performBlockAndWait: - 两者都在单独的线程中执行。

作为旁注,由于 NSURLConnection 在启动异步加载操作的同一线程上调用委托(delegate)方法 - 在我的例子中是主线程 - 使用后台上下文似乎根本没有必要。 NSURLConnections 无论如何都会在运行循环中传递它的事件。

关于ios - NSManagedObjectContext:带有通知中心的 performBlockAndWait 与 performBlock,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21146399/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com