Ios 用于读写的多个UIManagedDocument

Ios 用于读写的多个UIManagedDocument,ios,core-data,synchronization,uimanageddocument,Ios,Core Data,Synchronization,Uimanageddocument,我正在为iPhone构建一个选项卡栏应用程序,并将核心数据与两个UIManagedDocuments一起使用。在第一个选项卡中,我将数据写入数据库,在第二个选项卡中,我使用UIFetchedResultsController将数据读入UITableView 在应用程序开始时,如果我先写数据,然后再读取结果,它工作正常。结果立即显示在第二个选项卡中。然而,若我先读取一些数据,然后再向数据库中写入一些内容,结果将显示在第二个选项卡中,并有相当大的延迟,大约1分钟。如果两个UIManagedObjec

我正在为iPhone构建一个选项卡栏应用程序,并将核心数据与两个UIManagedDocuments一起使用。在第一个选项卡中,我将数据写入数据库,在第二个选项卡中,我使用UIFetchedResultsController将数据读入UITableView


在应用程序开始时,如果我先写数据,然后再读取结果,它工作正常。结果立即显示在第二个选项卡中。然而,若我先读取一些数据,然后再向数据库中写入一些内容,结果将显示在第二个选项卡中,并有相当大的延迟,大约1分钟。如果两个UIManagedObjectContext或两个UIManagedDocuments之间存在任何同步问题,那么在第一种情况下它是如何工作的?还有,有没有解决此延迟的方法?

确保UIManagedDocument最新的方法是确保正确保存更改。鉴于您上面显示的信息,我不确定您是如何管理文档或ManagedObjectContext的。影响这一点的因素太多了,无法给你一个100%具体的答案

因此,在不知道代码外观和如何管理上下文的情况下,我唯一能做的就是提供我在自己的项目中使用的内容。这可能会帮助您,也可能不会帮助您,但在通过UIManagedDocument处理核心数据方面,它帮助了我——不止一次

说到上下文: 我使用单例管理UIManagedDocument。我这样做是因为我不想处理你上面所说的问题——有多个managedObjectContext。当您开始处理多个上下文时,您会遇到一个问题,即除非您正确管理所有上下文,否则数据将不一致。如果您在其中一个上保存数据,但不更新另一个,那么您的数据可能会变得不同步。你还必须确保每个上下文都在属性线程上工作——苹果文档是理解为什么广告如何这甚至很重要的一个很好的资源

不过,关键是,这是使用UIManagedDocument时遇到的最大问题之一,它不像使用纯核心数据和SQL持久存储时那么糟糕。我发现的主要原因是UIManagedDocument实际上是如何保存到其UIDocument存储的。它想在什么时候储蓄是很难预测的。这使得了解UIManagedDocument何时会真正持久化,并让您的数据在黑暗中异常活跃。你最终不得不做各种愚蠢的事情,只是为了确保它随时可用

考虑到我有一个信念,许多人(也许是正确的)认为,使用核心数据是困难的,而UIManagedDocument使它比完全不使用它更容易。话虽如此,我不喜欢处理像UIManagedDocument这样简单的东西,因为它开始变得复杂——所以我使用了一个一直保持简单的东西,那就是单个UIManagedDocument的一个单独的共享实例,这样我就只有一个managedObjectContext需要处理

说到储蓄: 每当我对模型进行任何重大更改(创建、更新、删除、编辑),我总是确保调用[document updateChangeCount:UIDocumentChangeDone];之所以这样做,是因为我在使用UIManagedDocument时不使用undo manager NSUndoManager。只是因为我还没有必要这么做,再加上我讨厌你用它做的所有工作区垃圾

仅在主线程上工作: 每当我对UIManagedDocument或核心数据执行任何操作时,我总是确保它位于主线程上。我想我已经说过一次了,但我要再说一次:当您需要线程时,在线程中工作是有帮助的,但当您真正理解线程时也是如此。我喜欢在线程中工作,但这是以复杂度为代价的,这使得我不想在核心数据中工作。在这种情况下,我倾向于严格遵循主线,因为这样可以使事情简单易行

保存文档 当我确实需要确保UIManagedDocument保存并写入磁盘时,我编写并使用了两种随时可以调用的方法:saveDocument和forceSaveDocument

第一个saveDocument仅检查上下文中的更改。如果有,它会检查是否有新插入的对象。找到insertedObjects后,它将获得这些项目的perm ID。您可以认为这是一种很好的方法,可以确保您的核心数据模型是最新的,并且您的托管上下文处于安全状态,这样,当您的文档实际保存时,您可以将所有内容保存在ID中需要的状态,即实现了ID,您的上下文是干净的,您将要保存的内容表示模型的一种状态,一年一次 我的工作已经完成了

它的老大哥forceSaveDocument实际上首先调用saveDocument。同样,要确保实际模型/上下文已保存且正确。如果它返回successful YES,那么它将实际执行真正的保存,并通过savetour将文档写入磁盘

一些代码可能会有所帮助: 以下是这两种方法,以备不时之需:

-(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和核心数据时遵循的指导原则,并为我工作了大约3年。我肯定有比我聪明得多的男孩/女孩比我更好,但这些都是我所用的。我从他们那里得到的好处是,它使我不必担心如何管理我的数据,并让我有更多的自由来处理其他事情:

使用单例管理我的UIManagedDocument,直到绝对需要多个线程-然后迁移到多个上下文开始使用我从未需要过的多个上下文-但我再次尝试保持简单 当我对模型进行任何更改时,始终调用updateChangeCount:UIDocumentChangeDone。它重量很轻,影响很小。如果有的话,它将有助于确保您的文档保持最新,并且永远不会与您的数据太不同步。 不要使用撤销管理器,除非你真的需要它我还没有需要它 谨慎使用save/ForceSave,并且只有在绝对必要的删除是使用它的好理由时才使用。或者,如果您在一个视图控制器上创建了一个新项目,并需要在下一个视图控制器上使用它,但却迫不及待地等待核心数据和文档同步—这有点像踢它的屁股,说我反对您随时保存—立即保存lol。。 最后的想法 以上都是我自己的信念和理解。这些都来自于大量的研究、阅读,当想要把事情做对的时候,总是让人觉得很痛苦,同时保持简单。任何人都可以编写一个复杂的解决方案,但我认为最根本的问题始终是:你真的需要复杂性,还是只需要它来工作,这样你就可以专注于更复杂的问题

我相信上面的内容比你想要的要多得多,甚至可能会添加比你更多的问题。如果你需要一些链接和资源,让我知道,我会尝试把一些放在一起


不管怎样,希望这能有所帮助

使用单个共享UIManagedDocument实例解决了我的问题。这段代码对我很有帮助:谢谢你的回复。没问题,很高兴能帮上忙