2015-12-13 4 views
1

Существует несколько причин, по которым кто-то хочет объединить несколько NSManagedObjectModel. При поиске в Интернете все ответы заключаются в том, что это невозможно или что это возможно только для двух несвязанных объектов, которые разделяют одно или несколько отношений. См. Например, this и this.Создание модели NSManagedObjectModel из нескольких моделей

Однако с небольшим количеством работы (я думаю) можно объединить NSManagedObjectModels, даже если сущности связаны (как в родительском-дочернем), или если атрибуты распределены по нескольким моделям.

Хотя он не будет отображаться так же легко в редакторе модели Xcode, и переходы из коробки (возможно) не будут работать.

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

ответ

1

Некоторые вещи, которые я заметил:

  1. Копирование NSPropertyDescription (атрибут, отношения) копирует все свои ценности, но не объект, к которому она принадлежит. То же самое для destinationEntity и inverseRelationship.

  2. Таким образом, копирование NSPropertyDescription должно быть добавлено к сущности. В результате все дочерние объекты этого объекта автоматически получают свойство.

  3. Копирование NSEntityDescription не включает родительский объект. Поэтому дерево (из NSManagedObjectEntity) должно восстанавливаться вручную.

  4. Если вы установите родительский объект, то (дочерний) объект немедленно и автоматически наследует все его родительские свойства. Другими словами, когда вы запрашиваете сущность для своих атрибутов, этот объект уже знает обо всех его атрибутах. Он не будет сначала запрашивать родителя. (разумное предположение)

  5. Добавление объектов в модель заполняет сущности-адресаты и описания обратных отношений отношений. Описания добавленных объектов.

  6. Если вы не задали имя какой-либо сущности или собственности, прежде чем использовать его, основные данные будут жаловаться. То есть copy by name вместо аспекта стоимости.

  7. Добавление свойства к сущности, у которой уже есть свойство с тем же именем (либо само по себе, либо унаследовано от его предка), приведет к сбою основных данных.

Это переводится в следующий код:

extension NSPropertyDescription 
{ 
    var isPlaceholder : Bool { return self.userInfo?["isPlaceholder"] != nil } 
} 

extension NSEntityDescription 
{ 
    var isPlaceholder : Bool { return self.userInfo?["isPlaceholder"] != nil } 
} 

func mergeModels(models: [NSManagedObjectModel]) -> NSManagedObjectModel? 
{ 
    var entities : [String : NSEntityDescription] = [:] 

    //support functions 
    let makeEntity : String -> NSEntityDescription = { entityName in 
     let newEntity = NSEntityDescription() 
     entities[entityName] = newEntity 
     newEntity.name = entityName 
     return newEntity 
    } 

    let setParent : (String, NSEntityDescription) ->() = { parentName, child in 
     if let parent = entities[parentName] 
     { 
      parent.subentities.append(child) 
     } 
     else //parent has not yet been encountered, so generate it 
     { 
      let newParentEntity = makeEntity(parentName) 
      newParentEntity.subentities.append(child) 
     } 
    } 


    //rebuild model: generate new description for each entity and add non-placeholder properties 
    for model in models 
    { 
     for entity in model.entities 
     { 
      guard let entityName = entity.name else { fatalError() } 
      let mergedEntity = entities[entityName] ?? makeEntity(entityName) 

      //set entity properties 
      if !entity.isPlaceholder 
      { 
       mergedEntity.abstract = entity.abstract 
       mergedEntity.managedObjectClassName = entity.managedObjectClassName 
      } 

      //set parent, if any 
      if mergedEntity.superentity == nil, //no parent set 
       let parentName = entity.superentity?.name //but parent is required 
      { 
       setParent(parentName, mergedEntity) 
      } 

      //set properties 
      for property in entity.properties 
      { 
       if property.isPlaceholder || 
        mergedEntity.properties.contains({$0.name == property.name}) 
       { continue } 

       let newProperty = property.copy() as! NSPropertyDescription 
       mergedEntity.properties.append(newProperty) 

      } 
     } 
    } 

    //generate final model 
    let mergedModel = NSManagedObjectModel() 
    mergedModel.entities = Array(entities.values) //sets the destination entity and inverse relationship descriptions 
    return mergedModel 
} 

В managedObjectModel (редактор Xcode) установите «заполнитель» флаг в информации пользователя словаря объекта и/или имущества.

Генерация модели может быть уточнена путем установки дополнительных клавиш в словаре информации о пользователе, чтобы указать, какая модель имеет основной объект/атрибут/отношение (настройки) и соответствующую настройку этого фрагмента кода.

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

[Отказ от ответственности: насколько я могу судить, этот код должен работать. Нет гарантий, хотя.]

 Смежные вопросы

  • Нет связанных вопросов^_^