有条件地构建具有不同资产目录的应用程序

Posted

技术标签:

【中文标题】有条件地构建具有不同资产目录的应用程序【英文标题】:Conditionally build app with different asset catalogs 【发布时间】:2015-02-11 16:08:18 【问题描述】:

我的 Xcode 项目以具有多种配置的方式设置,允许我为我的应用程序的不同变体使用相同的代码库,但每个变体都有独特的元素,例如应用程序名称、版本、包标识符、图标、启动屏幕等。我已经按照这个网站进行了大部分设置: http://appfoundry.be/blog/2014/07/04/Xcode-Env-Configuration/

我还有一个 config.plist,其中包含与每个 Xcode 配置相关联的各种唯一设置,这些设置只有在构建时才会成功复制。这是运行脚本构建阶段的 sn-p 以执行此操作:

RESOURCE_PATH=$SRCROOT/$PRODUCT_NAME/config/$CONFIGURATION

BUILD_APP_DIR=$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.app

echo "Copying all files under $RESOURCE_PATH to $BUILD_APP_DIR"
cp -v "$RESOURCE_PATH/"* "$BUILD_APP_DIR/"

我的下一个目标是能够在构建时复制特定配置的资产目录,以避免将所有不同配置的图像捆绑到构建中,导致它变得臃肿。我已经用运行脚本尝试了与上面相同的解决方案,将复制行更改为包含递归选项(因为资产目录本质上是一个目录):

cp -rv "$RESOURCE_PATH/"* "$BUILD_APP_DIR/"

但是,当我这样做时,我的应用程序无法构建,并说它无法找到应用程序图标和启动图像。有什么想法吗?

【问题讨论】:

您能设置一个示例项目来尝试执行此操作吗?我正在考虑一些问题,但这完全取决于您如何在项目中设置资产目录。我很乐意提供帮助,这是一个非常有趣的想法! 与此同时,我一直在调查。我可能弄错了,但如果我查看我构建的包,我只会看到包含正确的应用程序图标,而不是其他的。看来您的问题实际上是由 xcode 机制在幕后解决的。你能验证一下吗? 抱歉这么久才回复。创建示例项目有点困难。不知道你的意思是Xcode实际上解决了我的问题。你能解释一下吗?它无法建立抱怨它找不到我的启动屏幕和图标。基本上,对于配置文件夹下的每个配置,我都有一个名为 images.xcasset 的资产目录。它像 config.plist 一样被复制。 我应该提到我必须取消选中 images.xcasset 的目标成员资格,就像 config.plist 一样。我怀疑这就是为什么我尝试构建应用程序时 Xcode 找不到它的原因。 听起来您真正想要的是拥有一个具有多个目标的项目。 This article 是对其工作原理的非常有用的描述。拥有多个目标允许您指定包含每个资产目录的目标,拥有多个 .plist 文件等。 【参考方案1】:

这是你可以做的事情:

为每个配置添加单独的资产目录,就像您通常将资产目录添加到项目中一样。假设对于这个例子,我们将这些目录称为 MediaForDebug.xcassets、MediaForAdHoc.xcassets 和 MediaForRelease.xcassets 确保新创建的资产目录都是您的目标的成员(所以不要在这里排除它们,我们稍后会这样做) 现在,如果尚未添加到您的构建设置中,请添加自定义 EXCLUDED_SOURCE_FILE_NAMES 用户定义设置。 有关要为此用户定义设置设置的值,请​​参见下面的屏幕截图。

通过这样做,Xcode 将只编译适当的资产目录,而忽略其他的。我已经在我们的一个项目中对此进行了测试,它按预期工作。

祝你好运!

备注:如果您使用的是 CocoaPods,您可能会遇到麻烦,因为 CocoaPods 添加了自己的构建步骤来编译您的资产,以及您的依赖项到 .car 文件中。有关此问题的讨论,请参阅https://github.com/CocoaPods/CocoaPods/issues/1546。 TL;DR:确保此步骤不在您的构建阶段执行,或编辑它们执行的 CocoaPods 脚本以不进行资产构建。

2019 年 1 月 19 日更新:使用最新的稳定版 Xcode (10.1) 和 Cocoapods (v1.5.3),它们可以通过上述解决方案开箱即用。无需更改 Cocoapods 脚本或构建步骤,只需按照说明设置 EXCLUDED_SOURCE_FILE_NAMES

【讨论】:

如果您有很多不同的配置,以下可能会派上用场: EXCLUDED_SOURCE_FILE_NAMES = Media*.xcassets INCLUDED_SOURCE_FILE_NAMES = MediaForAdHoc.xcassets 这样您就不必一一排除资产. “为每个配置添加单独的资产目录,就像您通常将资产目录添加到项目中一样。” -- 如何为每个配置添加单独的资产目录? 这个解决方案很棒,但是如果您使用的是同名资产,那么您将收到警告“图像集名称 xxx 被多个图像集使用”即使这些错误不代表最终状态。有解决办法吗?

以上是关于有条件地构建具有不同资产目录的应用程序的主要内容,如果未能解决你的问题,请参考以下文章

如何使用多个目标使用具有相同名称的不同资产

使用 Rails 3.1 资产管道有条件地使用某些 css

资产目录和多个目标

构建填充了资产目录的 tvOS 应用程序时出错

如何有条件地加载 iOS 7 和 iOS 6 的资产?

Xcode:根据预处理器标志从资产目录中排除构建中的图像