Отношения между моделями в NSManagedObjectModel из объединенных моделей?

Можно ли моделировать отношения между сущностями, определенными в отдельных NSManagedObjectModels, если сущности всегда используются в NSManagedObjectModel, созданной путем слияния соответствующих моделей?

Например, модель 1 определяет объект Foo с отношением (один к одному) toBar, а модель 2 определяет объект Bar с отношением (один к одному) toFoo. Я создам стек CoreData, используя -[NSManagedObjectModel mergedModelFromModels], объединив модель 1 и модель 2. Есть ли способ определить эти отношения либо в средстве моделирования данных, либо программно, чтобы они вели себя так, как если бы они были отношениями внутри модели?


person Barry Wark    schedule 24.09.2008    source источник


Ответы (1)


Ни модель 1, ни модель 2 нельзя будет загрузить во время выполнения, если они не имеют правильного формата, то есть если отношения toBar и toFoo не имеют адресатов. Кроме того, если модели 1 и 2 имеют модели с одинаковыми именами, вы не сможете создать из них объединенную модель; они не будут сливаться, они будут сталкиваться, что является ошибкой.

Однако вы можете использовать NSManagedObjectModel API вручную, чтобы загрузить каждую модель и вручную создать новую модель, содержащую объекты из обеих. Классы NSEntityDescription и NSPropertyDescription (и их подклассы) реализуют протокол NSCopying, поэтому в большинстве случаев вы должны просто иметь возможность копировать свойства из каждой модели компонента в общую модель.

Кроме того, все классы NS*Description поддерживают словарь userInfo, который вы можете редактировать в инструменте моделирования данных Xcode, который вы можете использовать, чтобы делать такие вещи, как пометить место назначения отношения как замещающее. Например, в модели 1 у вас может быть сущность Bar с ключом userInfo MyRealEntity, и вы можете проверить это при создании объединенной модели в качестве сигнала для использования реальной сущности.

Вы также захотите поместить резервные обратные отношения к своим резервным сущностям; они будут заменены реальными инверсиями после слияния. Однако вам не нужно полностью копировать ваши резервные объекты во всех моделях; вам нужны только обратные отношения, используемые в вашей реальной модели в стенде в сущности.

Таким образом, если ваш реальный 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, вы можете использовать подобные приемы, чтобы разбить свою модель на несколько моделей.

person Chris Hanson    schedule 26.09.2008