核心数据代码生成说明!

从Xcode8开始,Apple在Xcode数据模型编辑器中添加了新的Codegen设置,以帮助开发人员管理和维护其NSManagedObject子类。 Codegen设置包含3种可能的配置:

  • 手动/无
  • 类定义
  • 类别/扩展

最初,这3种配置可能看起来有些混乱,我发现实际上很难找到一篇好的文章来解释每种配置之间的区别以及使用哪种配置。

在本文中,我将详细介绍每种配置,并分析每种配置之间的差异,并提出一些建议,说明应该在核心数据项目中使用哪种配置以及如何使用它。 事不宜迟,让我们开始吧!


这是Xcode8之前的默认行为,开发人员必须手动创建和维护NSManagedObject子类的更改。

您可以尝试创建一个示例核心数据项目,添加一个新的实体调用TestEntity并按照此链接中的步骤生成NSManagedObject子类。

如果正确执行此步骤,Xcode将生成2个文件:

  TestEntity + CoreDataClass.swift 
TestEntity + CoreDataProperties.swift

生成这两个文件后,您应该可以在项目中使用TestEntity 。 尝试将以下代码行复制到您的应用程序委托中,您的项目应编译没有任何错误。

 让_ = TestEntity(context:persistentContainer.viewContext) 

在数据模型编辑器中创建实体时,此配置是默认的Codegen配置。 使用此配置,Xcode将自动生成所需的NSManagedObject子类,作为项目派生数据的一部分。

要查看实际情况,请打开先前创建的样本核心数据项目,然后删除两个TestEntity+CoreDataClass.swift TestEntity+CoreDataProperties.swift 您会注意到,删除两个文件后,您的项目将不再能够编译。 这是因为您对Codegen使用了手动/无配置。

现在尝试将Codegen配置更改为Class Definition,您会注意到您的项目现在可以再次编译而没有任何错误。

要查看自动生成的文件,请按cmd +单击TestEntity ,然后选择“跳转到定义”。

右键单击打开的TestEntity+CoreDataClass.swift然后选择“在Finder中显示”。

现在您应该可以同时看到TestEntity+CoreDataClass.swift TestEntity+CoreDataProperties.swift (由Xcode自动生成) 在查找器窗口中。 但是请注意,这两个文件均不在您的Xcode项目中,实际上它们都位于Xcode的“派生数据”文件夹中。

切勿编辑自动生成的文件,因为它们由Xcode管理,因此,每次构建项目时,它们都会被Xcode覆盖。

可以在类定义手动/无之间描述此配置。 Xcode将仅自动生成TestEntity+CoreDataProperties.swift 为您,您将必须管理和维护TestEntity+CoreDataClass.swift 你自己

将示例项目的Codegen配置更改为Category / Extension,您将注意到在派生数据中,Xcode不再自动生成TestEntity+CoreDataClass.swift 对您来说,您的项目将无法再次编译。

要解决该错误,您可以使用上述相同的方法来请求Xcode为您的项目创建TestEntity+CoreDataClass.swift ,但是Xcode还将为您的项目创建TestEntity+CoreDataClass.swift的副本,因此请确保将其删除从项目中删除,以避免与派生数据文件夹中的自动生成版本冲突。


希望上面的解释使您对每种Codegen配置的工作方式有更清晰的了解。 但是,您应该在下一个核心数据项目中使用哪一个?

类定义

此配置非常适合开发简单的应用程序或在原型开发阶段。 在编辑数据模型时,您不必担心更新或维护NSManagedObject子类,Xcode将为您解决这一问题。 但是,您对NSManagedObject子类没有任何控制,因此导致此配置使用起来不太灵活。

类别/扩展

此配置适用于大多数核心数据应用程序。 在大多数情况下,更新数据模型时无需执行任何操作。 但是,您可以灵活地将所需的任何自定义函数添加到NSManagedObject子类中。 让我们看一下以下用例:

假设您的TestEntity有一个名为base64的属性,它表示图像的base64编码字符串。 通过使用Category / Extension配置,您可以通过添加名为image的计算属性和有助于执行base64编码/解码操作的自定义函数来自定义TestEntity+CoreDataClass.swift 。 这是TestEntity+CoreDataClass.swift的示例: