核心数据:SQLite未立即更新

时间:2016-03-31 13:48:38

标签: ios sqlite core-data

有两个实体 - 文档和页面。文档与Page有一对多的关系。

添加文档时保存托管对象上下文。此时,它们中没有页面。在调试时我发现编写器上下文的save方法确实被调用并且执行时没有错误。我关闭并重新打开应用程序,我找不到以前保存的Document对象。但是,如果我在其中一个文档中添加了一个页面,那么Doc​​ument对象就会出现在表格中。我使用工具查看SQLite文件,但我的观察不是基于我在工具中看到的。即使我调试并查看存在的文档数量,当没有页面时我也会返回0。

我猜测持久存储协调器正在进行某种优化以批量编写。我可以强制它立即写入和更新持久性存储吗?在持久性存储对象上调用addPersistentStoreWithType时是否可以添加一个选项?

注意:仅供参考,我使用this模式来组织托管对象上下文

修正了问题。这是更新 所以,我一直在保存整个堆栈直到编写器上下文。这个bug非常愚蠢。我试图在主线程上保存主要上下文,如下所示:

- (void)saveMainContext {
[self.mainManagedObjectContext performBlock:^{
    // Ensure that the main object context is being saved on the main queue
    __block NSError *error = nil;
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.mainManagedObjectContext save:&error];
    });
    if(!error)
    {
        //Write to disk after saving on the main UI context
        [self saveWriterContext];
    } 

}];
}

如您所见,在尝试保存主上下文后,我保存了编写器上下文。但是,错误是我没有等待主要上下文完成保存。修复bug后,我的代码如下所示:

- (void)saveMainContext {
[self.mainManagedObjectContext performBlock:^{
    // Ensure that the main object context is being saved on the main queue
    dispatch_async(dispatch_get_main_queue(), ^{
        NSError *error = nil;
        [self.mainManagedObjectContext save:&error];
        if(!error)
        {
            //Write to disk after saving on the main UI context
            [self saveWriterContext];
        } 
    });
}];
}

而且,这解决了这个问题!我这是非常愚蠢的错误。

1 个答案:

答案 0 :(得分:1)

您确定要保存整个堆栈吗?如果您在私有上下文中进行更改,则需要保存该私有上下文。如果在主上下文中(从UI)进行更改,则需要保存该上下文。只有在您将所有其他上下文报告NO-hasChanges之后,才应保存编写器上下文(也就是设计中的主上下文)。

我怀疑这是你的问题。

对OP

的回应
  

嗯。不知道那个。谢谢!所以,如果我根本不检查“错误”,你是否建议我可能会好起来,只是检查保存的回报?

我所说的是你的保存应该是这样的(注意我也纠正你不必要的dispatch_async):

- (void)saveMainContext {
    [self.mainManagedObjectContext performBlock:^{
        // Ensure that the main object context is being saved on the main queue
        NSError *error = nil;
        if (![[self mainManagedObjectContext] save:&error]) {
            NSLog("Failed to save context: %@\n%@", [error localizedDescription], [error userInfo]);
            exit(1);
        }
        [self saveWriterContext];
    }];
}

dispatch_async将被忽略,因为您已经在正确的队列中。

-save:的调用会返回bool。如果和,如果返回NO,您是否对error做出了反应。