来自合并模型的NSManagedObjectModel中的跨模型关系?

时间:2020-03-06 14:41:33  来源:igfitidea点击:

如果始终在通过合并相关模型创建的NSManagedObjectModel中使用实体,则可以对在单独的NSManagedObjectModels中定义的实体之间的关系建模吗?

例如,假设模型1定义了具有" toBar"关系(一对一)的实体" Foo",模型2定义了具有" toFoo"关系(一对一)的实体" Bar"。我将使用-[NSManagedObjectModel mergedModelFromModels]构建CoreData堆栈,合并模型1和模型2. 是否有任何方法可以在数据建模器中或者以编程方式定义这些关系,以使其表现为模型内关系?

解决方案

除非它们的格式正确,也就是说,除非toBar和toFoo关系具有目的地,否则模型1和模型2都无法在运行时加载。此外,如果模型1和模型2具有相同名称的模型,则将无法从它们创建合并的模型。它们不会合并,它们会发生冲突,这是一个错误。

但是,我们可以手动使用NSManagedObjectModelAPI来加载每个模型,并手动创建一个包含两个实体的新模型。 NSEntityDescription和NSPropertyDescription类(及其子类)确实实现了NSCopying协议,因此在大多数情况下,我们应该只需要将属性从每个组件模型复制到整个模型即可。

此外," NS * Description"类均支持" userInfo"字典,我们可以在Xcode的数据建模工具中对其进行编辑,该字典可用于执行诸如将关系的目标标记为替身的操作。例如,在模型1中,我们可以有一个带有用户信息键MyRealEntity的Bar实体,并在创建合并模型时检查该实体,以作为使用真实实体的信号。

我们还需要将替代关系与替代实体联系起来。合并后,这些将被替换为实数逆。但是,我们不必在所有模型中都完全复制替代实体。我们只需要实体中的实体中在实际模型中使用的逆关系。

因此,如果真实Foo具有name属性,而真实Bar则具有kind属性,那么站立式FooBar将不需要这些,只需站立式toBar和toFoo关系。

这是一些代码,展示了我在说什么:

- (NSManagedObjectModel *)mergeModelsReplacingDuplicates:(NSArray *)models {
    NSManagedObjectModel *mergedModel = [[[NSManagedObjectModel alloc] init] autorelease];

    // General strategy:  For each model, copy its non-placeholder entities
    // and add them to the merged model. Placeholder entities are identified
    // by a MyRealEntity key in their userInfo (which names their real entity,
    // though their mere existence is sufficient for the merging).

    NSMutableArray *mergedModelEntities = [NSMutableArray arrayWithCapacity:0];

    for (NSManagedObjectModel *model in models) {
        for (NSEntityDescription *entity in [model entities]) {
            if ([[entity userInfo] objectForKey:@"MyRealEntity"] == nil) {
                NSEntityDescription *newEntity = [entity copy];
                [mergedModelEntities addObject:newEntity];
                [newEntity release];
            } else {
                // Ignore placeholder.
            }
        }
    }

    [mergedModel setEntities:mergedModelEntities];

    return mergedModel;
}

之所以可行,是因为相对于关系的目标实体和反向实体(以及实体的子实体)而言,在核心数据中复制NS * Description对象是按名称而不是按值。因此,虽然模型是可变的,也就是说,在将其设置为NSPersistentStoreCoordinator的模型之前,我们可以使用类似的技巧将模型分为多个模型。