多个 NSManagedObjectContext 或传递它?

Posted

技术标签:

【中文标题】多个 NSManagedObjectContext 或传递它?【英文标题】:Multiple NSManagedObjectContext or Pass it around? 【发布时间】:2014-04-01 15:18:30 【问题描述】:

所以我遇到了一种情况,由于某种原因,我有数据要保存,但直到我终止应用程序才完全保存。细节并不重要,但在查看我的代码时,我发现了以下内容:

在我的 App Delegate 中实例化

NSManagedObjectContext NSManagedObjectModel NSPersistentStoreCoordinator

我有一个后台线程,可以处理和保存大量数据 - 在这个线程中,我使用这个初始化调用创建了第二个 managedObjectContext:

- (void)initCoreDataWithNSPersistentStoreCoordinator:(NSPersistentStoreCoordinator *)storeCoordinator andLocationManager:(CLLocationManager *)manager 
    if (!managedObjectContext) 

        if (storeCoordinator != nil) 
            managedObjectContext = [[NSManagedObjectContext alloc] init];
            [managedObjectContext setPersistentStoreCoordinator:storeCoordinator];
        

     else 
        NSLog(@"Dual Init attempted!!");
    

    if (manager != nil) 
        [self setLocationManager:manager];
    

    /* Setup a Notification Handler now that COREData is initialized */
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(saveContext:)
                                                 name:@"saveContext"
                                               object:nil];

在我的代码中的其他任何地方(我没有看到保存问题)我实际上是在使用类似于这样的 prepareForSegue 方法传递原始上下文:

// Pass on managedObjectContext
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 

    // If the destination VC is able to take teh setManagedObjectContext method the current objectContext will be passed along.
    if ([segue.destinationViewController respondsToSelector:@selector(setManagedObjectContext:)]) 
        [segue.destinationViewController performSelector:@selector(setManagedObjectContext:)
                                              withObject:_managedObjectContext];
     else 

        NSLog(@"Segue to controller [%@] that does not support passing managedObjectContext", [segue destinationViewController]);
    

其中一种方法是否比另一种“更好”?我猜双重上下文是我公正数据刷新的原因,但我不太确定。但真正的问题是苹果“首选”的这些方法之一,如果是的话,是哪一种。此外,在这两种情况下我需要注意哪些陷阱。

谢谢!

【问题讨论】:

不是更好 - 适合情况。主上下文用于主线程。您需要在后台线程上使用不同的上下文。以上[[NSManagedObjectContext alloc] init]是您的实际代码吗?你确定你只有一个后台线程吗? 线程间共享同一个上下文有什么坏处吗? 是的,它不能正常工作... 您不能跨线程使用一个上下文,这违反了 Apple 关于 Core Data 上下文线程限制的规则。我建议在此处或 Apple 的有关核心数据和线程的文档上进行搜索。基本规则是:每个线程一个上下文。 【参考方案1】:

在视图控制器之间传递主托管对象上下文是正确的做法,因为它们都在主线程上运行。

这个问题可能与您的后台线程托管对象上下文有关。您应该为此使用不同的上下文,因为对上下文的所有更新都在正确的线程(队列)上进行非常重要,但是如果您有多个后台线程,那么您当前的代码将导致它们共享上下文,您将看到问题。

查看为每个后台线程创建不同的上下文。

【讨论】:

所以我将“主”上下文传递给了我的后台线程,现在所有问题都消失了 -> 但如果你说我做错了,那么强制同步的正确方法是什么? 正确的是每个线程的不同 MOC,每个后台线程将保存的更改合并到主 MOC

以上是关于多个 NSManagedObjectContext 或传递它?的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI:如何将 NSManagedObjectContext 传递到多个视图模型中

NSManagedObjectContext 通过通知中心问题在多个线程上保存/合并

如何在多个线程上处理 NSManagedObjectContext 和 NSManagedObject 创建和编辑?

NSManagedObjectContext 类别

NSManagedObjectContext类别

将块与 NSManagedObjectContext 一起使用 [重复]