没有目标的Xcode文件变体
如果您想使用其他替代配置来配置iOS / Mac(Swift或Objective-C)构建,则可以遵循许多不同的方法。 通常,您可以将它们分为两个集群:在运行时(例如,解析Info.plist
)或编译时(利用Swift编译条件/预处理器宏或定义新目标)进行切换。 显然,我们总是更喜欢编译时检查,但是开销经常会夸大其好处。
这篇文章将提出一种基于Xcode构建规则(与传统的Xcode目标相反)来控制文件变体选择的替代方法。
问题陈述
有很多解决方案可以构建不同风格的应用程序,这些应用程序可能在以下方面有所不同:
- 端点地址(例如分期与生产)
- 逻辑(例如,启用/禁用地理围栏检查)
有关更多详细信息,请允许我推荐这篇文章,其中详细介绍了其中的大多数内容。
长话短说,对于Swift开发,您可以选择:
- 使用
#if DEBUG ... #endif
结构来包含或禁用给定代码块的编译条件 - 单独的目标 ,其中每个目标都包含一个单独的专用文件,其中包含针对给定配置的特定代码
- 从
.plist
输入文件或环境变量进行运行时检查
每个都有一个缺点,请提及:
- 如果影响编译器的条件,可能会导致代码过多,导致代码混乱
- 单独的目标引入了不必要的需求,将所有“共享”代码库和配置都包含在其中
- 对于运行时配置,我们会丢失编译时检查。
如果我们可以有一个目标 ,该目标根据配置使用文件的特定变体,那不是很好吗?
解决方案:使用自定义构建规则使用或跳过.swift
文件
传统上,Xcode目标使您可以有选择地选择要编译的文件。 您可以利用它来用另一个指定其他baseURL
或完全不同的逻辑策略的源文件替换一个源文件。 为了这篇文章的缘故,让我们假设我们要使用两个不同的Configuration_X.swift
文件之一:
// Configuration_S.swift
结构配置{
让baseUrl =“ https://staging.example.com/”
} // Configuration_P.swift
结构配置{
让baseUrl =“ https://example.com/”
}
没有目标,我们可以使用Xcode项目中不太流行的自定义“构建规则”来实现,您可以在其中根据文件名指定如何处理项目文件。
添加自定义构建规则时,必须指定文件模式,要应用的Shell脚本以及脚本的输出文件。 然后,Xcode在编译过程中将评估您的脚本中与给定模式匹配的文件,而不是默认行为(例如,编译.swift
文件)。 请记住,自定义构建规则优先于嵌入规则-这使我们有机会覆盖默认的编译行为。
对于我们的解决方案,我们将遵循以下算法:
- 将
Configuration_X.swift
所有版本都包含在一个目标中 - Xcode项目指定了一个虚拟的构建规则 ,该规则吞下了您要跳过的文件(从构建中排除)
- 照常处理所有其他文件(格式为
xxxxx_x.swift
)
为了控制要在虚拟构建规则中吞噬的文件,我们将使用用户定义的设置CONFIGURATION_VARIANT
(设置名称取决于您)来创建单独的Xcode配置:
上面的配置意味着对于“调试”配置,我们希望选择带有“ S”后缀( xxxxx_S.swift
)的登台文件变体,以及对于带有“ P”后缀( xxxxx_P.swift
)的“发行”产品。
有很多其他选项可以指定用户定义的构建设置,例如xcodebuild终端命令的`buildsetting = value`参数。
回到我们新创建的构建规则,让我们指定我们要手动处理项目.swift文件的子集:
- 处理以
CONFIGURATION_VARIANT
以外的单字符后缀结尾的Swift文件(请注意,Xcode在这里使用简单的模式匹配,而不是更强大的正则表达式) - 该脚本在派生目录中创建带有
_skipped
后缀的空文件 - 指定Xcode应该处理刚刚创建的空文件,而不是原始的文件-从技术上讲,这里我们将文件的主体视为空文件。
请注意,我们在
$DERIVED_FILE_DIR
目录上进行操作,因此给定脚本可以在构建目录中创建文件,并且不会修改原始文件(可能在源代码控制下)。
结果是:不再有多个目标,不再有#if... #endif
块,也没有运行时检查—构建设置(例如,特定于配置)控制是否应包含给定文件。
可以在 GitHub 上 找到 演示该应用程序的示例应用程序 。
最后,请注意,此技术不仅限于.swift
文件。 通过对上述构建规则进行少量修改,您也可以将其应用于Objective-C文件,图像,资产或其他数据(例如.json文件)。
摘要
构建规则是iOS / Mac开发人员经常低估且几乎不使用的工具。 这篇文章演示了在编译过程中选择性地包括/排除.swift
文件如何有用。 现在,在沉浸于多目标项目或基于条件的代码的世界之前,我们还需要考虑另一种选择。
一个限制是我们只能使用单字符后缀标记(例如_A.swift,_B.swift,_1.swift等),因为Xcode在Build Rules选项卡中不支持glob或regex文件匹配。 随时复制 OpenRadar 建议,该建议使Build Rules对此具有更多控制权。
- 推视图控制器不显示从故事板添加的元素
- 如何将parameter passing给导航控制器内的弹窗视图控制器
- 你的iOS开发证书已被撤销?
- 为什么我应该使用单独的testing主机来运行XCTests,我应该怎么做?
- 如何使用UIImageRenderingModeAlwaysTemplate防止粗体图像
- 在iOS中将特定时间的文本添加到video
- 通过NSRegularExpression获取Javascript函数之间的具体值?
- void _UIPerformResizeOfTextViewForTextContainer中的断言失败
- 错误使用Swift – 实例成员不能用于types'ViewController'