gpt4 book ai didi

ios - NSManagedObject值正确,然后合并从父级到子级NSManagedObjectContext的更改时不正确

转载 作者:行者123 更新时间:2023-11-29 12:55:53 25 4
gpt4 key购买 nike

我在使用2 NSManagedObjectContext时遇到核心数据问题,该代码在不同的线程上运行,并将更改从父级迁移到子级。从本质上讲,我可以将更改从父母拉到孩子,但是这样做之后,更改立即丢失。

我正在构建的应用程序是一项用于在多个设备和服务器之间同步模型的测试。

包含与用户进行交互的对象的上下文位于主线程上,并被配置为同步上下文的子级,并以此方式创建(省略了错误检查)

NSManagedObjectContext *parentMOC = self.syncManagedObjectContext;
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

[_managedObjectContext performBlockAndWait:^() {
[_managedObjectContext setParentContext:parentMOC];
}];

syncManagedObjectContext是父上下文,并且是syncManager与服务器执行同步的位置。它收集用户修改的对象,将更改发送到服务器,然后将收到的更改合并回去。 syncManagedObjectContext还将其数据发送到 PersistentStoreCoordinator以存储在 SQLite中。上下文在后台“线程”上运行,因此同步和存储不会阻塞主线程。创建方法如下:

NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
_syncManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_syncManagedObjectContext performBlockAndWait:^(){
[_syncManagedObjectContext setPersistentStoreCoordinator:coordinator];
}];

同步逻辑流程

当syncManager从主上下文处理NSManagedObjectContextObjectsDidChangeNotification时,开始同步。以下是发生的情况的大致流程:
  • syncManager处理NSManagedObjectContextObjectsDidChangeNotification,它使它知道对象已在主线程上下文中更改。它在主上下文上调用save,将更改保存到syncMOC。
  • 当syncManager收到NSManagedObjectContextDidSaveNotification指示保存已完成时,它将从同步上下文中收集新更改的对象,并将更改发送到服务器。然后,它在同步MOC上进行保存,该MOC将数据发送到SQLite。请注意,每个对象都有一个我创建为可移植ID的uuid字段-请勿与Core Data的objectID和服务器提供的lastSynced时间戳混淆。
  • 服务器以发送的对象的更新时间戳以及已发生的任何其他更改作为响应。在说明问题的最简单的情况下,接收到的是一组记录,该记录由uuid和syncManager刚发送的对象的更新的lastSynced时间组成。
  • 对于每次更新,syncManager都会更新syncContext中的对象,并将该对象(而非uuid)的NSManagedObject objectID存储在数组中。
  • 然后,syncManager在同步MOC上进行保存以将数据写入磁盘,并发布一条消息,向主MOC提供更新对象的objectID数组。在这一点上,如果我对syncMOC中的所有实体进行访存并将其转储到日志中,则它们都具有正确的值。此外,如果我查看磁盘上的SQLite数据库,它也具有正确的值。
  • 这是用于在主线程上合并更新的缩略代码(删除了一些错误检查和非必要内容),并附有关于发生的情况的注释:(注意:我在代码中一直非常小心地使用performBlock及其在调试器中跟踪显示一切都发生在正确的线程上。)

  • -(void)syncUpdatedObjects: (NSNotification *)notification
    {
    NSDictionary *userInfo = notification.userInfo;
    NSArray *updates = [userInfo objectForKey:@"updates"];

    NSManagedObjectContext *ctx = self.managedObjectContext;

    [ctx performBlock:^() {
    NSError *error = nil;

    for (NSManagedObjectID *objID in updates) {
    NSManagedObject *o = [ctx existingObjectWithID:objID error:&error];
    // if I print out o or inspect in the debugger, it has the correct, updated values.


    if (o) {
    [ctx refreshObject:o mergeChanges:YES];
    // refreshObject causes o to be replaced by a fault, though the NSLog statement will pull it back.
    // NOTE: I’ve used mergeChanges:NO and it doesn’t matter

    NSLog(@"uuid=%@, lastSynced = %@", [o valueForKey:@"uuid”], [o valueForKey:@"lastSynced"]);
    // Output: uuid=B689F28F-60DA-4E78-9841-1B932204C882, lastSynced = 2014-01-15 05:36:21 +0000
    // This is correct. The object has been updated with the lastSynced value from the server.

    }

    }
    NSFetchRequest *request = [[NSFetchRequest alloc] init];

    NSEntityDescription *entity = [NSEntityDescription entityForName:@“MyItem"
    inManagedObjectContext:ctx];
    request.entity = entity;
    NSArray *results = [ctx executeFetchRequest:request error:&error];
    for (MyItem *item in results)
    NSLog(@"Item uuid %@ lastSynced %@ ", item.uuid, item.lastSynced);
    // Output: uuid B689F28F-60DA-4E78-9841-1B932204C882 lastSynced 1970-01-01 00:00:00 +0000
    // Now the objects have incorrect values!
    }];

    }

    万一您错过了它, NSLog语句后的注释中会出现问题。该对象最初具有来自父上下文的正确值,但随后它们变得不正确。具体来说看一下时间戳记。

    有谁知道为什么会这样?我应该注意,最后进行提取的工作是调试的一部分。我注意到程序中保留的NSManagedObjects没有正确的值,即使我看到上面代码中的内容已正确更新,并且通过uniqueing也应该对其进行更新。我认为可能会发生的是,当旧的对象还在时,我正在使用正确的值创建“额外”对象。但是,提取显示正确的对象只有正确的对象在身边,只有错误的值。

    还有一件事,如果我在此函数运行后在父上下文中执行相同的提取操作,则它会显示正确的值,就像 SQLite一样。

    任何帮助深表感谢!

    最佳答案

    我终于找到了这个问题的答案,并希望它可以对其他人有所帮助。

    我在某个时候注意到,回到主上下文的对象ID不正确
    核心数据ID-它们应该是永久的,但不是永久的。实际上,在合并过程中,我
    意识到我的主MOC中给定对象的ID和要合并的更改的ID
    这个物体既是暂时的,又是不同的。但是它们都不应该是永久性的。
    在Stack Overflow上搜索该问题后,我发现
    这个答案https://stackoverflow.com/a/11996957/1892468给出了已知Core的解决方法
    数据错误。

    所以问题不是我做错了,而是核心数据没有做任何事情
    说会的。解决方法是,在对主对象上下文进行保存操作期间,我添加了以下内容
    调用保存之前的代码。

    if ctx.insertedObjects.count > 0 {
    do {
    try ctx.obtainPermanentIDsForObjects(Array(ctx.insertedObjects))
    } catch {
    log.error("Unable toobtain permanent ids for inserts")
    }
    }

    修好了!所以我最初观察到的是合并实际上并没有
    地点。有2个对象还活着,应该是其中一个。

    关于ios - NSManagedObject值正确,然后合并从父级到子级NSManagedObjectContext的更改时不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21130866/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com