Ni le modèle 1 ni le modèle 2 ne peuvent être chargés au moment de l'exécution sauf s'ils sont bien formés, c'est-à-dire, à moins que les relations toBar
et toFoo
aient des destinations. En outre, si le modèle 1 et le modèle 2 ont des modèles portant le même nom, vous ne pourrez pas créer un modèle fusionné à partir de ces modèles; ils ne seront pas coalisés, ils entreront en collision, ce qui est une erreur. Toutefois, vous pouvez utiliser manuellement l'API NSManagedObjectModel
pour charger chaque modèle et créer manuellement un nouveau modèle contenant des entités des deux. Les classes NSEntityDescription
et NSPropertyDescription
(et ses sous-classes) implémentent le protocole NSCopying
. Dans la plupart des cas, vous devriez pouvoir copier les propriétés de chaque modèle de composant vers votre modèle global. Par ailleurs, les classes NS*Description
prennent toutes en charge un dictionnaire userInfo
que vous pouvez modifier dans l'outil de modélisation de données de Xcode, que vous pouvez utiliser pour étiqueter la destination d'une relation en tant que remplaçant. Par exemple, dans le modèle 1, vous pouvez avoir une entité Bar
avec une clé userInfo
MyRealEntity
et vérifier cela lors de la création de votre modèle fusionné, comme un signal pour utiliser l'entité réelle à la place.
Vous devrez également mettre des relations inverses en stand-in avec vos entités de remplacement; ceux-ci seront remplacés par de vrais inverses après la fusion. Cependant, vous n'avez pas à répliquer totalement vos entités de remplacement dans tous les modèles. Vous n'avez besoin que des relations inverses utilisées dans votre modèle réel dans une entité de peuplement.
Ainsi, si votre vrai Foo
a un attribut name
, et votre barre réel a un attribut kind
, votre stand en Foo
et Bar
aura pas besoin de ceux-ci, tout en se toBar
et toFoo
relations.
est ici un code montrant ce dont je parle:
- (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;
}
Cela fonctionne parce que la copie de NS*Description
objets de base de données est par nom plutôt que par la valeur par rapport à l'entité de destination d'une relation et inverse (et aux subentities d'une entité aussi bien). Ainsi, même si un modèle est mutable, c'est-à-dire avant qu'il ne soit défini comme modèle pour un NSPersistentStoreCoordinator
, vous pouvez utiliser des astuces comme celle-ci pour diviser votre modèle en plusieurs modèles.