合成文件
Tuist 可以在生成时生成文件和代码,为管理和使用 Xcode 项目带来一些便利。在本页中,你将了解此功能以及如何在项目中使用它。
Target 资源
Section titled “Target 资源”Xcode 项目支持向 target 添加资源。但是,它们给团队带来了一些挑战,尤其是在处理模块化项目时,源代码和资源经常被移动:
- 不一致的运行时访问:资源在最终产品中的位置以及如何访问它们取决于 target 产品。例如,如果你的 target 代表一个应用,资源会被复制到应用 bundle 中。这导致访问资源的代码对 bundle 结构做出假设,这不理想,因为它使代码更难理解,资源也难以移动。
- 不支持资源的产品:某些产品(如静态库)不是 bundle,因此不支持资源。因此,你必须使用不同的产品类型,例如框架,这可能会给你的项目或应用带来一些开销。例如,静态框架将静态链接到最终产品,并且需要一个构建阶段才能将资源仅复制到最终产品。或者对于动态框架,Xcode 会将二进制文件和资源都复制到最终产品,但会增加应用的启动时间,因为框架需要动态加载。
- 容易出现运行时错误:资源通过其名称和扩展名(字符串)来标识。因此,任何一个中的拼写错误都会导致尝试访问资源时出现运行时错误。这不理想,因为它不会在编译时被捕获,并可能导致发布版本崩溃。
Tuist 通过合成统一的 bundle 和资源访问接口来解决上述问题,抽象了实现细节。
Tuist 提供了用 Swift 声明 Info.plist 或 entitlements 等文件内容的接口。这对于确保跨 target 和项目的一致性以及利用编译器在编译时捕获问题很有帮助。你也可以提出自己的抽象来建模内容并在 target 和项目之间共享。
当你的项目被生成时,Tuist 会合成这些文件的内容并将它们写入相对于定义它们的项目目录的 Derived 目录。
Bundle 访问器
Section titled “Bundle 访问器”Tuist 合成一个访问包含 target 资源的 bundle 的接口。
target 将包含一个 Bundle 类型的扩展来暴露 bundle:
let bundle = Bundle.moduleObjective-C
Section titled “Objective-C”在 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 处创建它们,其中名称是资源的小驼峰命名版本。
| 资源 | 模板名称 |
|---|---|
| strings | Strings.stencil |
| assets | Assets.stencil |
| plists | Plists.stencil |
| fonts | Fonts.stencil |
| coreData | CoreData.stencil |
| interfaceBuilder | InterfaceBuilder.stencil |
| json | JSON.stencil |
| yaml | YAML.stencil |
| files | Files.stencil |
如果你想配置要合成访问器的资源类型列表,可以使用 Project.resourceSynthesizers 属性,传入你想使用的资源合成器列表:
let project = Project(resourceSynthesizers: [.string(), .fonts()])