多个UIManagedDocument For Read&写

时间:2014-06-14 09:04:09

标签: ios core-data synchronization uimanageddocument

我正在为iPhone构建一个标签栏应用程序,而我正在使用Core Data和两个UIManagedDocument。在第一个选项卡中,我将数据写入数据库,在第二个选项卡中,我将其读入UITableView UIFetchedResultsController

在应用程序开始时,如果我先写入数据,然后我读取结果,它就可以正常工作。结果立即显示在第二个选项卡中。但是,如果我首先读取一些数据,之后如果我向数据库写入内容,结果将显示在第二个选项卡中,相当长的延迟(差不多1分钟)。如果两个UIManagedObjectContext或两个UIManagedDocument之间存在任何同步问题,它在第一个条件下如何工作?而且,这种延迟有什么解决方案吗?

1 个答案:

答案 0 :(得分:1)

确保您的UIManagedDocument是最新的方式是确保您正确保存更改。根据您上面显示的信息,我不确定您是如何管理文档或托管对象的。有太多因素可能影响到这一点,以便能够给出100%具体的答案。

因此,如果不知道您的代码是什么样的,并且不知道如何管理您的上下文,我唯一能做的就是为您提供我在自己的项目中使用的内容。这可能会或可能不会对您有所帮助,但在通过UIManagedDocument处理核心数据时,它帮助了我 - 比一次更多 - 。

说到Context:

我使用单例来管理UIManagedDocument。我这样做是因为我不想处理你上面谈到的内容 - 拥有多个managedObjectContext。当您开始处理多个上下文时,除非您正确管理所有上下文,否则会遇到数据不一致的问题。如果您保存一个但不更新另一个 - 那么您的数据可能会变得不同步。您还必须确保每个上下文都在属性thread上运行 - Apple Docs是一个很好的资源,可以帮助您理解这个甚至是重要的广告。

关键是,这是使用UIManagedDocument 的最大问题之一,并不像您使用纯核心数据和使用时一样糟糕SQL持久性存储。我找到的主要原因是因为UIManagedDocument实际上如何保存到其UIDocument商店。 想要保存时,这是非常难以预测的。这使得知道你的UIManagedDocument何时会实际存在,并让你的数据在黑暗中变得怪异。你必须做各种愚蠢的事情,以确保它总是随时可用。

考虑到我有一种信念(很多,也许这是理所当然的,相信是一种无知的信念),使用核心数据很难,而且UIManagedDocument使得它比你没有使用它更容易。所有。话虽这么说,当我处理像UIManagedDocument这样简单的事情开始变得复杂时,我不喜欢它 - 所以我使用了一件始终保持简单的东西,那就是单一的,单一的共享实例UIManagedDocument,以便我只有1个managedObjectContext,永远,必须使用。

说到保存:

每当我对模型进行任何重大更改(创建,更新,删除,编辑)时,我总是确保调用[document updateChangeCount:UIDocumentChangeDone];我这样做因为我使用"撤消经理" (NSUndoManager)使用UIManagedDocument时。仅仅因为我还没有必要,加上因为我讨厌所有"解决方法"垃圾与你有关。

仅在主线程上工作:

每当我使用我的UIManagedDocument或Core Data执行任何时,我总是确保它在主线程上。我想我已经说了一次,但我会再说一遍:在你需要它时,在线程中工作是有帮助的,但是当你真正理解线程时也是如此。我喜欢在线程中工作,但它以复杂性为代价,这使得我不想在核心数据方面使用它们。在这种情况下,我倾向于严格遵守主线程,因为这样可以简单易用(对我来说)。

保存文件

当我绝对需要确保UIManagedDocument被"保存" (写入磁盘),我有两种我编写和使用的方法,我随时可以拨打这些方法:saveDocumentforceSaveDocument

第一个(saveDocument)仅检查上下文中的更改。如果有,则检查我们是否有任何新插入的对象。找到insertedObjects后,它将获取这些项的perm id。您可以将此视为确保核心数据模型是最新的,并且您的托管上下文处于安全状态的好方法,这样当您的文档实际保存时,您将获得所有内容< / em>保存在它需要进入的状态(你的id已经实现,你的上下文是干净的,你要保存的内容代表了你的模型在完成所有工作后的状态)。

它的大哥forceSaveDocument实际上先调用saveDocument。再次,确保您的实际模型/上下文得到保存和正确。如果它返回成功(YES),那么它实际上将通过saveToUrl进行实际保存并文档写入磁盘。

一些代码(希望它有帮助):

以下是这两种方法,如果它有帮助:

-(BOOL)saveDocument {
    NSManagedObjectContext *context = self.document.managedObjectContext;
    if(!context.hasChanges) return YES;

    NSSet *inserts = [context insertedObjects];
    if([inserts count] > 0) {
        NSError *error = nil;

        if(![context obtainPermanentIDsForObjects:[inserts allObjects] error:&error] && error) {
            [self reportError:error];
            return NO;
        }
    }

    return YES;
}

-(void)forceSaveDocument {
    if( [self saveDocument] ) {
        [self.document saveToURL:self.document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:self.onSaveBlock ? self.onSaveBlock : nil];
    }
}

一般规则/指南

总的来说,这些是我在使用UIManagedDocument和Core Data时遵循的指南(现在已经为我工作了大约3年)。我确信那些比我聪明的男人/女孩更好,但这些都有我用的东西。我从中获得的好处是,它让我不必担心关于管理我的数据,并让我有更多的自由来处理其他事情:

  • 使用单例来管理我的UIManagedDocument 直到绝对需要多个线程 - 然后迁移开始使用多个上下文(我从来不需要这样做然而 - 但我又试着保持简单)
  • 当我对模型进行任何更改时,
  • 始终致电updateChangeCount:UIDocumentChangeDone。它重量很轻,影响很小。如果有的话,它将有助于确保您的文档保持最新,并且永远不会与您的数据太不同步。
  • 除非您确实需要,否则不要使用撤消管理器(我还没有需要)
  • 在绝对必要时谨慎使用save / ForceSave,并且(删除是使用它的一个很好的理由。或者如果您在一个视图控制器上创建一个新项目并在下一个视图控制器上需要它,但是不能等待核心数据和文档同步 - 有点像在屁股上踢它并说'#34;我反对你随时保存 - 保存 now < / em> lol ..)

最后的想法

以上所有都是我自己的信念和理解。这些都来自于大量的研究,阅读,并且在想要做正确的事情时是一种痛苦,同时保持简单。任何人都可以编写复杂的解决方案 - 但我认为根本问题始终是:您是否真的需要复杂性,或者您是否只需要它来工作以便您可以专注于更复杂的问题?

我确信上述内容比您想要的更多,甚至可能会添加比您更多的问题。如果你需要一些链接和资源,请告诉我,我会尝试一些。

无论哪种方式,希望有所帮助。