iOS 后台保存在 Core Data 中

Posted

技术标签:

【中文标题】iOS 后台保存在 Core Data 中【英文标题】:iOS background save in Core Data 【发布时间】:2013-02-20 09:58:09 【问题描述】:

我想确保我的主线程永远不会阻塞,这就是为什么我想在后台保存我的核心数据。

我一直在阅读 Apple 文档以及此链接(以及许多其他文档,但我发现这个非常有用):http://www.cocoanetics.com/2012/07/multi-context-coredata/,尽管我无法正确构建架构。

在我的 AppDelegate.m 中:

- (NSManagedObjectContext *)managedObjectContext

    if (_managedObjectContext != nil) 
        return _managedObjectContext;
    

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) 
        _saveContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [_saveContext setPersistentStoreCoordinator:coordinator];

        _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        [_managedObjectContext setParentContext:_saveContext];
    
    return _managedObjectContext;

然后为了保存,我会这样做:

// var 'context' is the context coming from method managedObjectContext
// this code is in the same thread 'context' is created in (the main thread)
NSError *error = nil;
if ([context save:&error]) 
    [context.parentContext performBlock:^
        NSError *err = nil;
        if(![context.parentContext save:&err]) 
            NSLog(@"Error while saving context to the persistent store");
        
    ];
 else 
    // handle error

这是我通过阅读我之前提供的链接所得到的。保存不起作用,一旦应用程序关闭并重新打开,对任何托管对象所做的更改都将消失:它们从未保存到持久存储中。

我猜是有道理的,因为我在 1 个线程中创建了 2 个 NSManagedObjectContext,Apple 文档明确声明每个线程只有 1 个 NSManagedObjectContext。那么如何设置 _managedObjectContext 和 _saveContext 之间的父/子关系呢?我知道 _saveContext 需要在另一个线程中初始化,但我无法使用这种方法。

【问题讨论】:

父上下文创建自己的线程,你不必创建一个。您的代码看起来不错,我看不到明显的错误。您是否检查过内部保存操作是否实际执行?您还可以通过设置启动参数 -com.apple.CoreData.SQLDebug 1 来激活 Core Data SQLite 调试,然后您应该查看是否保存了某些内容。 我不确定上下文创建了自己的线程,我猜我对我发现的所有在 ios 5 之前写的帖子感到困惑。错误是我在某些时候传递了错误的上下文在我的代码中(还有一些其他后台队列用于获取)并且内部保存不是根上下文的保存。现在在我的脑海中(和代码)都整理好了,谢谢! ps:你能把这个作为答案发给我吗? 【参考方案1】:

(来自 cmets)

所有“新”托管对象上下文类型(NSMainQueueConcurrencyTypeNSPrivateQueueConcurrencyType)都管理自己的线程,无需在特殊线程上创建上下文。唯一要记住的是始终使用performBlockperformBlockAndWait 进行上下文中的操作。这样可以确保操作在正确的队列和线程上执行。

所以你的代码没问题。

(事实证明,错误是错误的上下文被传递给您的保存例程,因此内部保存没有在***上下文中完成。)

【讨论】:

以上是关于iOS 后台保存在 Core Data 中的主要内容,如果未能解决你的问题,请参考以下文章

Core Data,在后台线程中修改 NSManagedObject

Core Data 后台处理,保存不推送到主上下文

如何在应用程序处于后台时执行 Core Data 操作

使用 Core Data 保存后台位置更新

在后台线程上安全保存 Core Data 托管对象上下文的正确方法?

当应用程序后台运行时,Core Data 无法通过区域监控保存上下文