我可以从NSOperation上的完成块保存到托管对象上下文吗?

时间:2011-10-05 17:10:40

标签: cocoa core-data concurrency nsoperation nsoperationqueue

我的应用使用核心数据和NSOperationQueue。为了符合Apple的指导原则,我正在为每个队列创建一个单独的托管对象上下文。在我的例子中,这很简单:我有一个后台队列可以完成所有繁重的工作,另一个在主线程上只读取数据。

对我这样做似乎有意义:

  • 在后台队列中,创建一个对托管对象上下文执行大量工作的操作。
  • 将完成块添加到保存托管对象上下文的操作。

但是我在NSOperation文档中读到了:

  

无法保证完成块的确切执行上下文,但通常是辅助线程。因此,您不应该使用此块来执行任何需要非常特定的执行上下文的工作。相反,您应该将该工作分流到应用程序的主线程或能够执行此操作的特定线程。

当然,必须从“拥有”托管对象上下文的同一个线程执行此保存。但我并不总是清楚“线程”是否指的是操作队列。 (它有时会以或多或少的具体方式使用。)

我的'完成阻止'策略是否可行?

1 个答案:

答案 0 :(得分:1)

在代码中的任何地方做一个小技巧来解决这个问题: 创建moc:

    moc = [[NSManagedObjectContext alloc] init];
    [moc setUndoManager:nil];
    [moc setPersistentStoreCoordinator:coordinator];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(importerDidSave:) name:NSManagedObjectContextDidSaveNotification object:self.moc];

不要忘记删除观察者:

- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:self.moc];
[moc release];
[super dealloc];
}

最后,检查之前你将合并更改,如果是主线程:

- (void)importerDidSave:(NSNotification *)saveNotification {
NSLog(@"MERGE in client controller");
if ([NSThread isMainThread]) {
    [self.mainMoc mergeChangesFromContextDidSaveNotification:saveNotification];

} else {
    [self performSelectorOnMainThread:@selector(importerDidSave:) withObject:saveNotification waitUntilDone:NO];
}
}