我有一个项目使用Core Data和默认的AppDelegate。我在我的代码中有以下线程,其中下载了我的NSManagedObject WSObject
的图像。正如您将注意到的,我正在为此后台线程创建一个新的NSManagedObjectContext
。我试图在网上阅读不同的文档和其他论坛主题,但是在我的对象保存在后台上下文中之后,我无法理解如何在AppDelegate中通知我的主要上下文。
- (void) downloadImageForObjectID:(NSManagedObjectID*)objectID {
dispatch_queue_t imageDownloaderQueue = dispatch_queue_create("imagedownloader", NULL);
dispatch_async(imageDownloaderQueue, ^{
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
context.persistentStoreCoordinator = [(AppDelegate *)[[UIApplication sharedApplication] delegate] persistentStoreCoordinator];
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
WSObject *item = (WSObject*)[context objectWithID:objectID];
item.image.data = [item.image download];
if ([context hasChanges]) {
NSError *error = nil;
[context save:&error];
}
});
dispatch_release(imageDownloaderQueue);
}
有人可以告诉我要添加到此方法和AppDelegate以使其正常工作吗?据我所知,当我在后台线程中保存上下文时,会发送NSManagedObjectContextDidSaveNotification
。我应该向AppDelegate添加什么代码来收听此通知以及收到通知后该怎么做?
EDIT1: 我已将观察者添加到后台线程中。
if ([context hasChanges]) {
NSError *error = nil;
NSManagedObjectContext *mainContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeHandler:) name:NSManagedObjectContextDidSaveNotification object:mainContext];
[context save:&error];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:mainContext];
}
但AppDelegate中的mergeHandler
永远不会被调用。
答案 0 :(得分:12)
在使用您注册NSManagedObjectContextDidSaveNotification
的AppDelegate类定义的通知处理程序中,您只需执行以下操作:
- (void)myManagedObjectContextDidSaveNotificationHander:(NSNotification *)notification
{
// since we are in a background thread, we should merge our changes on the main
// thread to get updates in `NSFetchedResultsController`, etc.
[self.managedObjectContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) withObject:notification waitUntilDone:NO];
}
假设self.managedObjectContext
引用您的主NSManagedObjectContext
,那就是它。
最简单的可能是在保存之前注册您的上下文,并在之后注销:
if ([context hasChanges]) {
NSError *error = nil;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myManagedObjectContextDidSaveNotificationHander:) name:NSManagedObjectContextDidSaveNotification object:context];
[context save:&error];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:context];
}
答案 1 :(得分:4)
跟进gschandler,
你可以在appDelegate中找到:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(myManagedObjectContextDidSaveNotificationHander:)
name:NSManagedObjectContextDidSaveNotification
object:nil];
如果您将nil
作为对象传递,则会收到您指定的name
的所有通知,无论是哪个对象都已发送通知。
NSNotificationCenter Class Reference
notificationSender
观察者想要接收其通知的对象;也就是说,只有此发件人发送的通知才会传递给观察者 如果您通过nil,通知中心不会使用通知的发件人来决定是否将其发送给观察者。
有了这个,您还应该收到主线程上下文的通知,因此您需要进行一些过滤以避免进入主线程保存的循环,获取通知发生更改并再次保存并获取通知等。