跳转到内容

合成文件

Tuist 可以在生成时生成文件和代码,为管理和使用 Xcode 项目带来一些便利。在本页中,你将了解此功能以及如何在项目中使用它。

Xcode 项目支持向 target 添加资源。但是,它们给团队带来了一些挑战,尤其是在处理模块化项目时,源代码和资源经常被移动:

  • 不一致的运行时访问:资源在最终产品中的位置以及如何访问它们取决于 target 产品。例如,如果你的 target 代表一个应用,资源会被复制到应用 bundle 中。这导致访问资源的代码对 bundle 结构做出假设,这不理想,因为它使代码更难理解,资源也难以移动。
  • 不支持资源的产品:某些产品(如静态库)不是 bundle,因此不支持资源。因此,你必须使用不同的产品类型,例如框架,这可能会给你的项目或应用带来一些开销。例如,静态框架将静态链接到最终产品,并且需要一个构建阶段才能将资源仅复制到最终产品。或者对于动态框架,Xcode 会将二进制文件和资源都复制到最终产品,但会增加应用的启动时间,因为框架需要动态加载。
  • 容易出现运行时错误:资源通过其名称和扩展名(字符串)来标识。因此,任何一个中的拼写错误都会导致尝试访问资源时出现运行时错误。这不理想,因为它不会在编译时被捕获,并可能导致发布版本崩溃。

Tuist 通过合成统一的 bundle 和资源访问接口来解决上述问题,抽象了实现细节。

Tuist 提供了用 Swift 声明 Info.plist 或 entitlements 等文件内容的接口。这对于确保跨 target 和项目的一致性以及利用编译器在编译时捕获问题很有帮助。你也可以提出自己的抽象来建模内容并在 target 和项目之间共享。

当你的项目被生成时,Tuist 会合成这些文件的内容并将它们写入相对于定义它们的项目目录的 Derived 目录。

Tuist 合成一个访问包含 target 资源的 bundle 的接口。

target 将包含一个 Bundle 类型的扩展来暴露 bundle:

let bundle = Bundle.module

在 Objective-C 中,你将获得一个 {Target}Resources 接口来访问 bundle:

NSBundle *bundle = [MyFeatureResources bundle];

资源通过其名称和扩展名使用字符串来标识。这不理想,因为它不会在编译时被捕获,并可能导致发布版本崩溃。为了防止这种情况,Tuist 将 SwiftGen 集成到项目生成过程中,以合成访问资源的接口。借助这一点,你可以放心地访问资源,利用编译器来捕获任何问题。

Tuist 默认包含模板来合成以下资源类型的访问器:

资源类型合成的文件
图片和颜色Assets+{Target}.swift
字符串Strings+{Target}.swift
属性列表{NameOfPlist}.swift
字体Fonts+{Target}.swift
文件Files+{Target}.swift

注意:你可以通过将 disableSynthesizedResourceAccessors 选项传递给项目选项来禁用每个项目合成资源访问器。

如果你想提供自己的模板来合成对其他资源类型的访问器,这些资源类型必须由 SwiftGen 支持,你可以在 Tuist/ResourceSynthesizers/{name}.stencil 处创建它们,其中名称是资源的小驼峰命名版本。

资源模板名称
stringsStrings.stencil
assetsAssets.stencil
plistsPlists.stencil
fontsFonts.stencil
coreDataCoreData.stencil
interfaceBuilderInterfaceBuilder.stencil
jsonJSON.stencil
yamlYAML.stencil
filesFiles.stencil

如果你想配置要合成访问器的资源类型列表,可以使用 Project.resourceSynthesizers 属性,传入你想使用的资源合成器列表:

let project = Project(resourceSynthesizers: [.string(), .fonts()])