无法将 xcassets 分配给 Xcode 11 上的主要目标

Can't assign xcassets to the main target on Xcode 11

在 Xcode 11 我的 .xcassets 上,在 Xcode 10 上不会导致任何问题,导致编译失败并显示以下消息:

error: Multiple commands produce '/Users/user/Library/Developer/Xcode/DerivedData/project-enjiypsgxtcdbnaripixgtnjlagx/Build/Products/Debug-iphonesimulator/project.app/Assets.car':
1) Target 'project' (project 'project') has compile command with input '/Users/user/sandbox/project/Resources/buttons.xcassets'
2) That command depends on command in Target 'project' (project 'project'): script phase “[CP] Copy Pods Resources”

我能够编译项目的唯一方法是从目标中删除 .xcassets,但明显的缺点是它们在构建时不可用。

PS:这发生在 2 个 ObjC 项目中。

请检查您的依赖项是否有一些 pods 使用 'resources'(不是 'resources_bundle')到 link 在 podspec 中它自己的 xcassets。 这种方式已被弃用,因为它的输出文件名为'Assets.car'。与你的项目xcassets的编译输出名称相同。

中的只是部分正确:是的,出现这种情况是因为pod阶段产生了Assets.car作为输出文件,与输出重合xcassets 的名称 - 因此 Multiple commands produce... 错误:一个命令是脚本阶段 [CP] Copy Pods Resources 另一个 - 你自己项目的编译命令。

但是从输出文件中删除 Assets.car 将导致构建系统无法看到脚本处理文件,因此它会跳过它(阅读 this了解更多详情)。所以我们可以做的是 add Assets.carinput 文件 - 这将创建脚本的依赖项,告诉构建系统在执行脚本之前等待文件。

注意:就像上面的解决方案一样,每次更新 pods 后都必须执行此操作,因为每次 运行 pod install 都会生成 [CP] Copy Pods Resourcespod update

Xcode->文件->工作区设置->构建系统->遗留构建系统

example

为了确保所有构建步骤都以正确的顺序执行,同时尽可能多的并行步骤,Xcode需要知道每个构建步骤依赖于哪些输入文件和哪些输出文件它会生成。

例如如果步骤 A 依赖于一个输入文件,该输入文件是步骤 B 的输出文件,则步骤 B 肯定必须在步骤 A 之前 运行。如果两个步骤都不需要另一个步骤的输出文件,则它们都可以 运行 并行.

虽然多个步骤肯定可以依赖于同一个输入文件,但不可能多个步骤产生与那种情况相同的输出文件,最后一个步骤 运行s 将覆盖输出文件无论哪个步骤先 运行,这意味着生成的输出文件内容将是不可预测的,这是构建过程中的一个错误,应该创建可预测的结果!

在您的情况下,问题在于您的 Copy Resources 构建阶段包含一个(或多个).xcassets 个包。 Xcode 不会只是复制这些包,而是将它们组合起来,转换和优化它们的内容,并创建一个名为 Assets.car 的文件,其中包含项目中所有资产目录的内容。

然而,如果您集成一个 Pod,并且这个 Pod 也有一个资产目录,则会发生完全相同的事情,并且会创建第二个 Assets.car 文件,现在 Xcode 有一个问题:两次构建步骤都说他们创建了一个 Assets.car 文件。哪一个会赢?这两个文件中的哪一个会出现在最终的应用程序中?那么依赖于这个文件的其他步骤呢?在完成哪些构建步骤后,他们必须 运行?这是一个 Xcode 无法解决的严重问题。

目前有两种可能的解决方案:

  1. 使用框架。当您使用框架而不是静态库时,Pods 的资源最终不会位于主应用程序的资源文件夹中,而是位于构建框架的资源文件夹中。您需要做的就是将 use_frameworks! 添加到您的 Podfile 中,无论是顶级还是仅针对特定目标。缺点是您的整体应用大小会增加一点,应用启动时间也会增加一点。

  2. 让 Pod 作者修复 Pod。 resources s/he 应使用 resources_bundle 而不是 Podspec 文档也强烈推荐。使用 resources 实际上还有其他缺点(资源文件未优化,不同 Pods 之间可能会出现名称冲突),而使用资源包是安全的,无论 Pods 是否作为静态库嵌入或作为动态框架。但是请注意,仅更改 Podspec 是不够的,所有加载捆绑资源的代码都必须采用 load them from the correct bundle(该名称将在使用 resources_bundle 时被称为Podspec 文件,您还必须为包命名。

针对此问题有一个正在进行的错误报告,您可以在这里找到它:
https://github.com/CocoaPods/CocoaPods/issues/8122

但目前的问题是,除了上面提到的两个之外,所有可能的解决方案基本上都是一个丑陋的 hack,而 Cocoapods 开发人员并不乐意实施丑陋的 hack。最好的解决方案,尽管看起来很难,可能是根本不解决这个问题,而是停止在 Podspec 文件中支持 resources,并使 resources_bundle 对 Pods 是强制性的包含自己的资源。

在您的库项目中,例如“LADetailPage”,打开 Targets 的“Build Phases”,创建一个名为“Copy Files”的预定义阶段,然后将您的 *.xcassets 拖到新阶段。

然后库不会在构建时从 *.xcassets 文件生成 Assets.car,相反,cocoapods 将 *.xcassets 复制到导入库的主项目,以及主项目将所有 *.xcassets 构建到一个 Assets.car 文件中。

在您的 pod 文件的顶部添加以下行,就在 platform :ios

之后
install! 'cocoapods', :disable_input_output_paths => true

Reference