在应用程序和框架中实现的核心数据代码生成子类的转换失败

Casting fails for core data codegen subclasses implemented in both app and framework

我正在尝试使用 NSManagedObject sub类 的新 Xcode 自动代码生成器(在本例中设置为 "Class Definition",因为我不需要任何自定义逻辑)具有 "Cocoa Touch Framework" 目标的项目。

我创建了这个 Cocoa Touch Framework 目标(我们称之为 "CoreDataFramework")以包含与核心数据处理(创建实体、更新实体等)相关的所有代码,因此应用程序和应用扩展可以使用相同的代码(应用扩展尚未添加)。

应用程序启动时,出现此错误消息:

"Class X 在 .../DerivedData/.../CoreDataFramework 和 .../AppName.app/AppName[ 中实现=50=]".

我认为这是因为自动生成的文件在 "target membership".

中同时设置了应用程序和框架

在旧版本中,我手动创建了 NSManagedObject sub类,并且能够通过将那些 类 的目标成员设置为仅框架来以某种方式修复此错误,错误消失并且该应用程序仍然能够使用这些 类.

但是现在子类文件是自动生成的,我不能改变它们的目标成员,所以app和framework都有同一个子类的定义。

这里的大问题是当应用程序使用框架代码获取其中一个子类:假设应用程序要求一个新的"User"实体,框架代码returns 新的 "User" 但随后应用程序代码因错误而崩溃:

"无法将类型 'CoreDataFramework.User' 的值转换为 'AppName.User'"

假设我想使用 codegen 在 "Class Definition" 模式下继续生成,并且我不想键入 "CoreDataFramework.User" 或 "AppName.User" 而不仅仅是 "User" 无处不在,我该如何解决这个铸造问题?或者即使我将 codegen 切换为 "Category/Extension" 我该如何解决这个问题?这里的目标是不要回到 "Manual/None".

更新:

核心数据堆栈代码,仅按照 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,所以代码中的致命错误永远不会显示。

解法:

感谢 Dave Weston 带领我走上了正确的道路。对我有用的解决方案是将数据模型文件移动到框架并将其目标成员资格更改为仅框架(这导致 sub类 仅存在于框架中,而不是在双方都实现)。然后我更改了核心数据堆栈初始化代码,以便它可以通过访问框架包而不是主包来正确加载数据模型,如下所示:

{
    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)")
            }
        })
    }
}

仅在框架中生成模型 类,然后当您想要引用这些模型时只需导入框架 类。