私が気づいたいくつかのこと:
NSPropertyDescription (属性、関係) をコピーすると、そのすべての値がコピーされますが、それが属するエンティティはコピーされません。destinationEntity と inverseRelationship についても同様です。
したがって、コピーされた NSPropertyDescription をエンティティに追加する必要があります。その結果、そのエンティティのすべての子エンティティも自動的にプロパティを取得します。
NSEntityDescription のコピーには、親エンティティは含まれません。そのため、(NSManagedObjectEntity の) ツリーは手動で再構築する必要があります。
エンティティの親を設定すると、その (子) エンティティは、すべての親プロパティを即座に自動的に継承します。つまり、エンティティにその属性を尋ねると、このエンティティはすでにすべての属性を知っています。最初にその親を照会しません。(合理的な仮定)
エンティティをモデルに追加すると、宛先エンティティと、追加されたエンティティの関係の説明の逆関係の説明が入力されます。
使用する前にエンティティまたはプロパティの名前を設定しないと、コア データからエラーが発生します。これは、値の側面ではなく、名前によるコピーです。
同じ名前のプロパティを既に持っているエンティティにプロパティを追加すると (それ自体から、またはその祖先から継承されたもの)、コア データが不平を言うようになります。
これは次のコードに変換されます。
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 エディター) で、エンティティおよび/またはプロパティのユーザー情報辞書に「プレースホルダー」フラグを設定します。
ユーザー情報ディクショナリに追加のキーを設定して、主要なエンティティ/属性/関係 (設定) を持つモデルを指定し、このコード フラグメントを適切に調整することで、モデル生成を改良できます。
ただし、複数のモデルの使用を避けることができる場合は、使用しないでください。標準的な単一モデルのアプローチに固執することで、あなたの人生はずっとシンプルになります。
[免責事項: 私の知る限り、このコードは機能するはずです。ただし、保証はありません。]