NSManagedObjectContext 和 performBlock,iOS 8 上的变化?

Posted

技术标签:

【中文标题】NSManagedObjectContext 和 performBlock,iOS 8 上的变化?【英文标题】:NSManagedObjectContext and performBlock, changes on iOS 8? 【发布时间】:2014-11-10 14:41:22 【问题描述】:

我有一个使用这个简单代码的旧项目(从 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】:

调用-[NSManagedObjectContext init] 只是-[NSManagedObjectContext initWithConcurrencyType:] 的包装器,带有参数NSConfinementConcurrencyType。这会创建一个 NSManagedObjectContext 的实例,它使用过时的线程限制模型 - 使用队列。使用 initinitWithConcurrencyType: 创建并传递值 NSConfinementConcurrencyType 的上下文与队列方法 performBlock:performBlockAndWait: 不兼容。

使用-[NSManagedObjectContext initWithConcurrencyType:] 创建您的上下文,并根据需要传递NSPrivateQueueConcurrencyTypeNSMainQueueConcurrencyType。结果创建的上下文performBlock:performBlockAndWait: 兼容,并将使用iOS 5 中引入的队列限制模型。

【讨论】:

谢谢。我认为我从 Apple Docs 中引用的那句话具有误导性:-)

以上是关于NSManagedObjectContext 和 performBlock,iOS 8 上的变化?的主要内容,如果未能解决你的问题,请参考以下文章

NSManagedObjectContext 和 performBlock,iOS 8 上的变化?

CoreData 和 NSManagedObjectContext

应用退出和重新启动时不保存 NSManagedObjectContext

用于关系的嵌套 NSManagedObjectContext 和 NSFetchedResultsController

NSManagedObjectContext 帮助

NSManagedObjectContext 异步导入、保存和通知主上下文