核心数据:子上下文是否为新插入的对象获取永久的objectID?

Jor*_*rge 29 concurrency nested core-data nsmanagedobjectcontext ios

我有一个应用程序有两个托管对象上下文设置如下:

  • 父上下文:NSPrivateQueueConcurrencyType,链接到持久性存储.
  • 主要上下文:NSMainQueueConcurrencyType,父上下文的子项.

当将新的托管对象插入主上下文时,我保存主上下文,然后保存父上下文,如下所示:

[context performBlockAndWait:^{
    NSError * error = nil;
    if (![context save: &error]) {
        NSLog(@"Core Data save error %@, %@", error, [error userInfo]);
    }
}];

[parentContext performBlock:^{
    NSError *error = nil;
    BOOL result = [parentContext save: &error];
    if ( ! result ) {
        NSLog( @"Core Data save error in parent context %@, %@", error, [error userInfo] );
    }
}];
Run Code Online (Sandbox Code Playgroud)

我的理解是,当首次创建管理对象时,它具有临时性objectID.然后保存主上下文,并且此对象及其临时ID将转到父上下文.然后保存父上下文.保存最后一个上下文后,objectID父上下文中的临时变换为永久变形objectID.

所以:

  • 永久对象ID是否会自动传播回主(子)上下文?
  • 当我强制获取对象永久ID时 [NSManagedObjectContext obtainPermanentIDsForObjects:error:],然后对应用程序进行后台处理,重新激活它,重新加载,使用主要上下文获取对象objectWithID:,并访问属性,我得到

    "CoreData无法解决......".

这种方法有什么问题?

Jod*_*ins 42

这是一个已知的错误,希望很快得到修复,但一般来说,获取永久ID就足够了,只要在将数据保存到第一个子项之前这样做,并且只包含插入的对象:

[moc obtainPermanentIDsForObjects:moc.insertedObjects.allObjects error:&error]
Run Code Online (Sandbox Code Playgroud)

在某些复杂的情况下,最好在创建实例后立即获取永久ID,尤其是在您具有复杂关系的情况下.

你怎么以及何时打电话obtainPermanentIDsForObjects

我没有关注应用程序崩溃的部分.也许更好的解释会有所帮助.


小智 10

正如Jody所说,当使用子ManagedObjectContext在后台线程中创建一个新的NSManagedObject时,您必须通过在保存之前执行以下操作来强制创建永久ID:

NSError *error = nil;

[threadedMOC obtainPermanentIDsForObjects:threadedMOC.insertedObjects.allObjects error:&error];

BOOL success = [threadedMOC save:&error];
Run Code Online (Sandbox Code Playgroud)

恕我直言,以这种方式做到这一点并不是很直观 - 毕竟,在你保存之前,你需要一个永久性的ID!但这是它似乎工作的方式.如果您在保存后要求提供永久ID,则该ID仍然是临时的.在Apple Docs中,您实际上可以使用以下内容来确定对象的ID是否是临时的:

BOOL isTemporary = [[managedObject objectID] isTemporaryID];
Run Code Online (Sandbox Code Playgroud)