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

时间:2008-09-24 22:27:01

标签: cocoa macos core-data nsmanagedobject nsmanagedobjectcontext

如果实体总是在通过合并相关模型创建的NSManagedObjectModel中使用,是否可以建模在单独的NSManagedObjectModel中定义的实体之间的关系?

例如,假设模型1定义了一个具有关系(一对一)Foo的实体toBar,而模型2定义了一个具有关系的实体Bar(一个到一个) -one)toFoo。我将使用-[NSManagedObjectModel mergedModelFromModels]构建一个CoreData堆栈,合并模型1和模型2.有没有办法在数据建模器中或以编程方式定义这些关系,以便它们的行为就像它们是模型内关系一样?

1 个答案:

答案 0 :(得分:16)

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

但是,您可以手动使用NSManagedObjectModel API来加载每个模型,并手动创建包含两者实体的新模型。 NSEntityDescriptionNSPropertyDescription类(及其子类)确实实现了NSCopying协议,因此在大多数情况下,您应该能够将每个组件模型的属性复制到整个模型中。< / p>

此外,NS*Description类都支持您可以在Xcode的数据建模工具中编辑的userInfo字典,您可以使用该字典来执行标记关系目标作为替身的操作。例如,在模型1中,您可以拥有一个Bar实体,其userInfoMyRealEntity,并在创建合并模型时检查它,作为使用真实实体的信号。< / p>

您还希望将替代关系置于您的替身实体中;这些将在合并后被真正的逆转所取代。但是,您不必在所有模型中完全复制您的替身实体;您只需要在实体中的实际模型中使用的反向关系。

因此,如果您的真实Foo具有name属性,并且您的真实条形码具有kind属性,则您的替补FooBar赢了不需要那些,只需要支持toBartoFoo关系。

以下是一些代码,展示了我所说的内容:

- (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的模型之前 - 您可以使用这样的技巧将模型分解为多个模型。