来自合并模型的NSManagedObjectModel中的跨模型关系?
如果始终在通过合并相关模型创建的NSManagedObjectModel中使用实体,则可以对在单独的NSManagedObjectModels中定义的实体之间的关系建模吗?
例如,假设模型1定义了具有" toBar"关系(一对一)的实体" Foo",模型2定义了具有" toFoo"关系(一对一)的实体" Bar"。我将使用-[NSManagedObjectModel mergedModelFromModels]
构建CoreData堆栈,合并模型1和模型2. 是否有任何方法可以在数据建模器中或者以编程方式定义这些关系,以使其表现为模型内关系?
解决方案
除非它们的格式正确,也就是说,除非toBar和toFoo关系具有目的地,否则模型1和模型2都无法在运行时加载。此外,如果模型1和模型2具有相同名称的模型,则将无法从它们创建合并的模型。它们不会合并,它们会发生冲突,这是一个错误。
但是,我们可以手动使用NSManagedObjectModel
API来加载每个模型,并手动创建一个包含两个实体的新模型。 NSEntityDescription和NSPropertyDescription类(及其子类)确实实现了NSCopying协议,因此在大多数情况下,我们应该只需要将属性从每个组件模型复制到整个模型即可。
此外," NS * Description"类均支持" userInfo"字典,我们可以在Xcode的数据建模工具中对其进行编辑,该字典可用于执行诸如将关系的目标标记为替身的操作。例如,在模型1中,我们可以有一个带有用户信息键MyRealEntity的Bar实体,并在创建合并模型时检查该实体,以作为使用真实实体的信号。
我们还需要将替代关系与替代实体联系起来。合并后,这些将被替换为实数逆。但是,我们不必在所有模型中都完全复制替代实体。我们只需要实体中的实体中在实际模型中使用的逆关系。
因此,如果真实Foo
具有name
属性,而真实Bar则具有kind
属性,那么站立式Foo
和Bar
将不需要这些,只需站立式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的模型之前,我们可以使用类似的技巧将模型分为多个模型。