NSManagedObjectContext和performBlock,在iOS 8上有什么变化?

3
我是一名有用的助手,可以为您翻译文本。以下是我翻译的结果:

我有一个旧项目(从iOS 7开始),其中包含以下简单代码:

在AppDelegate中,我创建managedObjectContext:

- (NSManagedObjectContext *)managedObjectContext {
    // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (!coordinator) {
        return nil;
    }
    _managedObjectContext = [[NSManagedObjectContext alloc] init];
    [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    return _managedObjectContext;
}

然后,我在视图控制器中执行更新操作:

    [context performBlock:^{
        [context deleteObject:anObject];

        NSError *error = nil;
        if (![context save:&error])
        {
            NSLog(@"Error saving context");
        }
    }];

我确定这段代码在iOS 7.0上运行正常,但是在iOS 8上的performBlock:调用时会崩溃,并显示以下错误:

只能在使用队列创建的NSManagedObjectContext上使用-performBlockAndWait:。

我可以通过像这样更改NSManagedObjectContext实例的init方法来解决这个错误:

_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

但我不明白为什么这种行为会改变。在NSManagedObjectContext的文档中,您可以阅读到以下内容:
“这样做的后果是,上下文认为默认所有者是分配它的线程或队列 - 这是由调用其init方法的线程确定的。”
因此,在我的第一个示例中,使用简单的init调用,上下文的队列所有者是主线程。 performBlock:调用也在主线程上进行,因此我不明白为什么会出现此错误。我有什么遗漏还是iOS 8中的一个错误?
1个回答

1
调用-[NSManagedObjectContext init]实际上只是-[NSManagedObjectContext initWithConcurrencyType:]的一个包装,使用参数NSConfinementConcurrencyType。这将创建一个使用过时的线程约束模型(不使用队列)的NSManagedObjectContext实例。使用init或带有传递值NSConfinementConcurrencyTypeinitWithConcurrencyType:创建的上下文与performBlock:performBlockAndWait:方法不兼容。
请使用-[NSManagedObjectContext initWithConcurrencyType:]创建上下文,并根据需要传递NSPrivateQueueConcurrencyTypeNSMainQueueConcurrencyType。由此创建的上下文与performBlock:performBlockAndWait:兼容,并将使用在iOS 5中引入的队列约束模型。

谢谢。我认为我从苹果文档中引用的那句话有误导性 :-) - LombaX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接