Cocoa 无法在具有existingObjectWithID的子上下文中检索临时对象:错误:

Cocoa 无法在具有existingObjectWithID的子上下文中检索临时对象:错误:,cocoa,core-data,magicalrecord,Cocoa,Core Data,Magicalrecord,我已经在托管对象上下文中创建了一个对象,但尚未保存。此外,我还创建了一个子上下文,并希望在此上下文中修改此对象。为了能够修改这个对象,我必须在子上下文中检索这个临时对象 我使用MagicalRecord的方法MR\u inContext:,它使用方法existingObjectWithID:error:。但这不会返回给定临时对象ID的对象。方法objectWithID:似乎可以工作。我不明白为什么existingObjectWithID:error:不起作用,但是objectWithID:在这种

我已经在托管对象上下文中创建了一个对象,但尚未保存。此外,我还创建了一个子上下文,并希望在此上下文中修改此对象。为了能够修改这个对象,我必须在子上下文中检索这个临时对象

我使用MagicalRecord的方法
MR\u inContext:
,它使用方法
existingObjectWithID:error:
。但这不会返回给定临时对象ID的对象。方法
objectWithID:
似乎可以工作。我不明白为什么
existingObjectWithID:error:
不起作用,但是
objectWithID:
在这种情况下起作用

- (void)testTemporaryObjectInChildContext {
    NSURL *modelURL = [[NSBundle bundleForClass:SSDProject.class] URLForResource:@"SSDProject" withExtension:@"momd"];
    NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

    NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    [coordinator MR_addInMemoryStore];

    NSManagedObjectContext *mainContext = [NSManagedObjectContext MR_mainQueueContext];
    mainContext.persistentStoreCoordinator = coordinator;

    SSDProject *project = [SSDProject MR_createInContext:mainContext];

    NSManagedObjectContext *childContext = [NSManagedObjectContext MR_confinementContextWithParent:mainContext];

    // Fails
    NSError *error = nil;
    XCTAssertNotNil([childContext existingObjectWithID:project.objectID error:&error], @"");
    NSLog(@"Error: %@", error);

    // Succeeds
    XCTAssertNotNil([childContext objectWithID:project.objectID], @"");
}

objectWithID:
始终返回一个对象,但该对象可能无效(并且在尝试使用它时可能引发异常)
existingObjectWithID:error:
在返回之前检查是否存在,如果找不到对象,则返回nil。因此,使用
existingObjectWithID:error:
是安全的选项


在尝试在另一个上下文中访问新对象之前,您应该先保存它,或者干脆不使用另一个上下文(不清楚为什么要执行您尝试执行的操作…。

原因
existingObjectWithID:error:
返回
nil
这里简单地说,对象不存在于该上下文中,因为它是来自不同上下文的临时对象

如果在一个托管对象上下文中创建对象但不保存,则该对象仅存在于该上下文中。任何其他托管对象上下文都无法了解它。它不在他们的内存中,而且因为它不在持久存储中,所以他们无法找到它。调用
existingObjectWithID:error:
时,上下文检查内存中的内容,必要时检查持久存储。对于来自不同上下文的未保存对象,两次检查都找不到任何内容

保存更改后,对象将写入持久存储文件,然后其他上下文可以找到它。此时,
existingObjectWithID:error:
将为ID返回非
nil


调用
objectWithID:
将返回一个对象,但不是您可以使用的对象。该方法假定您提供了一个有效的对象ID,因此它不会检查持久存储。如果对象存在,其数据将在正常情况下出错。如果没有,你会得到一个例外。当您知道对象存在并且想要更快的响应时,此方法非常有用。在您的情况下,对象不存在,因此调用此方法会给您一个定时炸弹,它会炸毁您的应用程序。

我使用多个上下文进行阶段性更改,这样我就可以丢弃每个子上下文及其更改。不幸的是,我无法保存上一个上下文。此外,我不想使用ID为的objectWithID:,因为我无法完全确定该对象是否始终存在。那么,如果不保存该对象,为什么要在父上下文中创建该对象呢?简单来说,用户可以取消该过程并放弃所有更改。我仍然不明白为什么这会阻止在子上下文中创建该对象。这就是您需要做的…我一直认为,子上下文在从存储协调器获取对象之前从父上下文获取对象,即使对象尚未保存。好的,您关于objectWithID:不测试存储中是否存在该对象的解释将解释存在的差异objectWithID:错误:。因此,唯一的解决方案是获得对象的永久性:错误:?这有什么坏处吗?坏处是这不是一个解决方案。当然,您将获得一个永久ID,但该对象仍然不存在于持久存储中,因此其他上下文仍然找不到它。你确实需要一个永久身份证,但光靠它是不够的。另一个上下文必须有某种方式来定位对象。该对象不应该对其他上下文可见,而只能对子上下文可见。要使其在子上下文中可定位而不保存父上下文,唯一的方法是使用GetainPermanentidForObjects:错误:很遗憾,子上下文是另一个上下文。我有一个子上下文(主队列)保存到父上下文(专用队列)中,然后另一个子上下文共享同一父上下文,使用对象的objectID检索对象。我的假设是这样的,因为你读到的每一篇文章都说父上下文被当作是孩子的永久存储,但是我发现,不,我必须将父上下文保存到(真实的)永久存储中,这样才能工作。对象是临时的还是永久的似乎无关紧要。