我正在尝试在具有“Cocoa Touch Framework”目标的项目中使用 NSManagedObject 子类的新 Xcode 自动代码生成(在这种情况下设置为“类定义”,因为我不需要任何自定义逻辑)。
我创建了这个 Cocoa Touch Framework 目标(我们称之为“CoreDataFramework”)来包含与核心数据处理(创建实体、更新实体等)相关的所有代码,因此应用程序和应用程序扩展都可以使用相同的代码(应用程序扩展尚未添加)。
当应用程序启动时,会出现以下错误消息:
“ X 类在 .../DerivedData/.../CoreDataFramework 和 .../AppName.app/AppName 中都实现了”。
我认为这是因为自动生成的文件在其“目标成员资格”中设置了应用程序和框架。
在旧版本中,我手动创建了 NSManagedObject 子类,并且通过将这些类的目标成员资格设置为仅框架,以某种方式能够修复此错误,错误消失了,应用程序仍然能够使用这些类。
但是现在子类文件是自动生成的,我无法更改它们的目标成员资格,因此应用程序和框架都有同一个子类的定义。
这里的大问题是当应用程序使用框架代码获取这些子类之一时:假设应用程序要求一个新的“用户”实体,框架代码返回新的“用户”但随后应用程序代码崩溃并出现错误:
“无法将‘CoreDataFramework.User’类型的值转换为‘AppName.User’ ”
假设我想使用 codegen 继续在“类定义”模式下生成,并且我不想在任何地方键入“CoreDataFramework.User”或“AppName.User”而不是“User”,我该如何解决这个铸造问题?或者即使我将 codegen 切换到“Category/Extension”,我该如何解决这个问题?这里的目标是不回到“手动/无”。
更新:
核心数据堆栈代码,仅按照 Dave Weston 的建议将数据模型移动到框架后:
{
let persistentContainer = NSPersistentContainer(name: "DataModel")
persistentContainer.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error (error), (error.userInfo)")
}
})
}
目前,此代码和数据模型文件都在框架中。出于某种原因,尝试创建容器的行是打印此错误的行:CoreData: error: Failed to load model named DataModel,因此代码中的致命错误永远不会显示。
解决方案:
感谢戴夫韦斯顿带领我走上正确的道路。对我有用的解决方案是将数据模型文件移动到框架并将其目标成员资格更改为仅框架(这导致子类仅存在于框架中,而不是在双方都实现)。然后我更改了核心数据堆栈初始化代码,以便通过访问框架包而不是主包来正确加载数据模型,如下所示:
{
let frameworkBundle = Bundle.init(identifier: "bundle.id.of.framework")
let dataModelURL = frameworkBundle!.url(forResource: "DataModelName", withExtension: "momd")!
let managedObjectModel = NSManagedObjectModel(contentsOf: dataModelURL)
let persistentContainer = NSPersistentContainer(name: "DataModelName", managedObjectModel: managedObjectModel!)
persistentContainer.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
}
}