无法使用existingObjectWithID检索子上下文中的临时对象:error:

时间:2014-03-19 16:08:59

标签: cocoa core-data magicalrecord

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

我使用MagicalRecord的方法MR_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], @"");
}

2 个答案:

答案 0 :(得分:2)

existingObjectWithID:error:返回nil的原因只是对象不存在,因为它是来自不同上下文的临时对象。

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

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

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

答案 1 :(得分:0)

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

您应该在尝试在其他环境中访问新对象之前保存新对象,或者只是不使用其他上下文(不清楚为什么要执行您尝试执行的操作...)。