如果错误消息引用了核心数据文件,请阅读此答案
简介:您可能同时具有自动生成的和手动生成的Core Data管理的对象类文件。
如果错误的第一行引用的是Foo + CoreDataProperties.o或Foo + CoreDataClass.o文件,则此答案适用。例:
error: Multiple commands produce '/Users/me/Library/Developer/Xcode/DerivedData/MyApp-uebslaqdwgldkjemijpdqmizgyzc/Build/Intermediates.noindex/ MyApp /Debug-iphonesimulator/ MyApp.build/Objects-normal/x86_64/Foo+CoreDataProperties.o':
1) Target ' MyApp ' (project ' MyApp ') has compile command for Swift source files
2) Target ' MyApp ' (project ' MyApp ') has compile command for Swift source files
可以通过展开“ 编译记录”的“编译Swift源文件”部分来查看根本原因。例如:
<unknown>:0: error: filename "Address+CoreDataClass.swift" used twice: '/Users/myUserName/Projects/Jnky/Foo+CoreDataProperties' and '/Users/jk/myUserName/Developer/Xcode/DerivedData/MyApp-uebslaqdwgldkjemijpdqmizgyzc/Build/Intermediates.noindex/MyApp.build/Debug/MyApp.build/DerivedSources/CoreDataGenerated/Jnky/Foo+CoreDataProperties.swift'
提到的第一个文件在您的项目目录中有一个源文件,该文件是通过在“项目浏览器”中选择数据模型并单击菜单中的“ 编辑器” >“ 创建托管对象子类”来生成的。。此功能是在Xcode 7左右添加的。
第二个文件是同名文件,但被埋在Xcode的中DerivedData
。如果数据模型()文件包含在目标的“ 编译源”构建阶段中,则此文件将在每次构建过程中由Xcode自动生成。此功能是在Xcode 9左右添加的。根据Codegen弹出窗口的设置,为每个实体/类生成零个,一个或两个文件。当您在编辑数据模型时选择一个实体时,该弹出窗口将显示在Data Model Inspector中。.xcdatamodeld
设置为:
- 手动/无不生成文件
- 类别/扩展名一个文件,Foo + CoreDataProperties.m或.swift,其中包含一个Objective-C类别或Swift扩展名。
- 类定义会生成相同的Category / Extension文件,此外还会生成Foo + CoreDataClass.m或.swift,其中包含类声明和定义。
因此,您会看到问题,当习惯了较旧Xcode的开发人员(如我)开始在较新的Xcode中进行项目时。我们认为我们需要使用创建托管对象子类菜单项来创建我们可以在项目导航器中看到的文件,而又没有意识到我们在Codegen弹出窗口中的设置导致Xcode创建重复文件,Apple “聪明”不会显示在项目导航器中,因为他们不信任开发人员阅读并注意标题中的注释//此文件是自动生成的,不应进行编辑。
解决方案1-使用较旧的方法
您可以仅使用一种设置来禁用数据模型的所有自动Codegen:
- 打开问题目标的构建阶段(在Project Navigator中,选择项目,然后在出现的TARGETS列表中,选择问题目标,然后选择Build Phases)。
- 展开“ 编译源”条目,然后找到问题数据模型(
.xcdatamodeld
文件)。
- 从编译列表中删除它
- 确保数据模型包含在“ 复制捆绑包资源”列表中。
解决方案2-初学者的核心数据魔术
在这里,您将以全新的方式全力以赴。
- 将数据模型保留在“ 编译源”中。
- 在数据模型中的每个Entity Inspector中,将Codegen设置为Class Definition。
- 在项目浏览器中,删除并丢弃所有Foo + CoreDataClass文件,然后将任何Foo + CoreDataProperties.m或.swift文件重命名为Foo + MyProperties之类的文件。
- 在每个Foo + MyProperties.m或.swift文件中,如果存在Xcode生成的属性,请删除这些属性,因为它们将位于Codegen创建的隐藏文件中。
使用此解决方案,您的类定义是从每个构建中的数据模型自动生成的。您甚至看不到它们。它是Core Data Magic,对初学者而言非常好用且简单。
解决方案3-适用于大多数实际应用
但是,如果您真的想添加非托管属性,则解决方案2不好。(Objective-C不允许将属性添加到类别中,Swift不允许将存储的属性添加到扩展中。)因此,在大多数实际应用中,您可能希望在解决方案1和解决方案2之间过渡一半…
- 将数据模型保留在“ 编译源 ”列表中
- 在数据模型中的每个Entity Inspector中,将Codegen设置为Category / Extension。
- 在项目浏览器中,删除并丢弃所有Foo + CoreDataClass.m或.swift文件,并且为了减少将来的混乱,将任何Foo + CoreDataProperties.m或.swift文件重命名为Foo.m或.swift。
- 确保每个Foo.m或.swift文件都包含类定义,您可以在其中添加自己的非托管属性。
(对Positron的回答表示感谢。我在这里的回答解释了Positron的答案(我的解决方案1)起作用的原因,并添加了Solution 2和Solution3。)