Кросс-модельные отношения в NSManagedObjectModel из объединенных моделей? - PullRequest
9 голосов
/ 25 сентября 2008

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

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

1 Ответ

16 голосов
/ 26 сентября 2008

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

Однако вы можете использовать API NSManagedObjectModel вручную, чтобы загрузить каждую модель и вручную создать новую модель, которая содержит объекты из обоих. Классы 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 объектов в Базовых данных осуществляется по имени, а не по значению по отношению к целевому объекту отношения и обратно (и также к субъектам объекта). Таким образом, хотя модель является изменчивой, то есть до того, как она будет установлена ​​как модель для NSPersistentStoreCoordinator, вы можете использовать такие приемы, чтобы разбить вашу модель на несколько моделей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...