Межмодельные связи в NSManagedObjectModel из объединенных моделей?
-
02-07-2019 - |
Вопрос
Возможно ли моделировать отношения между объектами, которые определены в отдельных NSManagedObjectModels, если объекты всегда используются в NSManagedObjectModel, который создается путем объединения соответствующих моделей?
Например, скажем, модель 1 определяет сущность Foo
с отношениями (один к одному) toBar
и эта модель 2 определяет сущность Bar
с отношениями (один к одному) toFoo
.Я создам стек CoreData, используя -[NSManagedObjectModel mergedModelFromModels]
, объединяющий модель 1 и модель 2.Есть ли какой-либо способ определить эти отношения либо в средстве моделирования данных, либо программно, чтобы они вели себя так, как если бы они были отношениями внутри модели?
Решение
Ни модель 1, ни модель 2 не будут доступны для загрузки во время выполнения, если они не будут правильно сформированы, то есть если toBar
и toFoo
у отношений есть пункты назначения.Кроме того, если модели 1 и 2 имеют одинаковые имена, вы не сможете создать из них объединенную модель;они не будут объединены, они будут сталкиваться, что является ошибкой.
Однако вы можете использовать NSManagedObjectModel
API вручную загружает каждую модель и вручную создает новую модель, содержащую объекты из обеих.Тот Самый NSEntityDescription
и NSPropertyDescription
классы (и их подклассы) действительно реализуют NSCopying
таким образом, в большинстве случаев вы должны просто иметь возможность копировать свойства из каждой компонентной модели в вашу общую модель.
Кроме того, NS*Description
все классы поддерживают userInfo
словарь, который вы можете редактировать в инструменте моделирования данных Xcode, который вы можете использовать для выполнения таких действий, как пометка места назначения связи в качестве дублера.Например, в модели 1 у вас может быть Bar
сущность с userInfo
Клавиша MyRealEntity
и проверьте это при создании вашей объединенной модели в качестве сигнала для использования реальной сущности вместо нее.
Вы также захотите установить резервные обратные отношения к своим резервным объектам;они будут заменены реальными инверсиями после слияния.Однако вам не обязательно полностью копировать свои резервные объекты во всех моделях;вам нужны только обратные отношения, используемые в вашей реальной модели в stand in entity.
Таким образом, если ваш реальный Foo
имеет name
атрибут, и ваш реальный Бар имеет 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
объекты в Core Data являются поименованными, а не по значению по отношению к объекту назначения отношения и обратными (а также к подразделам объекта).Таким образом, пока модель изменчива, то есть до того, как она будет установлена в качестве модели для NSPersistentStoreCoordinator
— вы можете использовать подобные трюки, чтобы разбить вашу модель на несколько моделей.