核心数据:SQLite 没有立即更新

Posted

技术标签:

【中文标题】核心数据:SQLite 没有立即更新【英文标题】:Core Data: SQLite not being updated immediately 【发布时间】:2016-03-31 13:48:37 【问题描述】:

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

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

我猜 Persistent Store Coordinator 正在做某种优化以批量写入。我可以强制它立即写入和更新持久存储吗?在持久存储对象上调用addPersistentStoreWithType 时,我可以添加一个选项吗?

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

解决了这个问题。这是更新 因此,我将整个堆栈一直保存到 writer 上下文。这个错误非常愚蠢。我试图像这样在主线程上保存主上下文:

- (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];
     

];

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

- (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】:

您确定要保存整个堆栈吗?如果您在私有上下文中进行更改,则需要保存该私有上下文。如果您在主上下文中进行更改(从 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做出反应。

【讨论】:

谢谢马库斯!我浏览了整个堆栈,并确保按照您的建议按顺序保存上下文,并找到了错误。非常感谢!是的,我应该将 hasChanges 添加到我的保存方法中。 并且保存后不要检查错误。您关注的作者不正确。检查来自-save: 的返回并回复。即使没有发生错误,也可以填充错误。 嗯。不知道。谢谢!那么,如果我根本不检查“错误”而只检查保存的返回,您是否建议我可能会过得很好? 更新答案以澄清我的 cmets 关于error

以上是关于核心数据:SQLite 没有立即更新的主要内容,如果未能解决你的问题,请参考以下文章

更改核心数据堆栈后使用核心数据创建 SQLite 文件后未更新

更新了核心数据模型,没有新版本,如何修复?

将本地 sqlite 文件发送到服务器

核心数据不直接保存到 sqlite

在应用程序运行时替换 Core Data sqlite 文件,数据不更新

当应用程序未运行时,使用推送通知的内容更新 SQLite