生成的文件
Tuist 可以在生成时创建文件和代码,从而简化 Xcode 项目的管理和开发工作。在本页中,你将了解这项功能以及如何在项目中使用它。
目标资源#
Xcode 项目支持向目标添加资源。然而,这会给团队带来一些挑战,尤其是在处理模块化项目时,因为源代码和资源经常会被移动:
- 运行时访问不一致:资源在最终产品中的位置以及访问方式取决于目标的产品类型。例如,如果目标代表一个应用程序,资源会被复制到应用程序包中。这会导致访问资源的代码对包结构做出假设,这并不是理想的做法,因为它使代码更难理解,也不利于资源的迁移。
- 不支持资源的产品类型:某些产品类型(如静态库)不是包,因此不支持资源。为此,你不得不改用其他产品类型,例如框架,但这可能会给项目或应用增加额外开销。例如,静态框架会静态链接到最终产品,并且需要一个构建阶段来仅将资源复制到最终产品中。或者使用动态框架,Xcode 会将二进制文件和资源都复制到最终产品中,但由于需要动态加载框架,这会增加应用的启动时间。
- 容易出现运行时错误:资源通过名称和扩展名(字符串)进行标识。因此,任何拼写错误都会导致在尝试访问资源时出现运行时错误。这并不是理想的情况,因为这些错误无法在编译时被捕获,可能会导致发布版本崩溃。
Tuist 通过生成统一的接口来访问包和资源来解决上述问题,从而抽象掉实现细节。
虽然通过 Tuist 生成的接口访问资源并非强制要求,但我们推荐使用,因为它使代码更易于理解,也更方便资源的迁移。
资源#
Tuist 提供了在 Swift 中声明文件内容(如 Info.plist 或权限配置)的接口。这有助于确保目标和项目之间的一致性,并利用编译器在编译时捕获问题。你还可以创建自己的抽象来建模内容,并在目标和项目之间共享。
当你的项目生成时,Tuist 会合成这些文件的内容,并将它们写入相对于定义它们的项目目录的 Derived 目录中。
我们建议将 Derived 目录添加到项目的 .gitignore 文件中。
包访问器#
Tuist 会生成一个接口,用于访问包含目标资源的包。
Swift#
目标将包含一个 Bundle 类型的扩展,用于暴露该包:
let bundle = Bundle.module
Objective-C#
在 Objective-C 中,你将获得一个接口 {Target}Resources 来访问包:
NSBundle *bundle = [MyFeatureResources bundle];
目前,Tuist 不会为仅包含 Objective-C 源代码的内部目标生成资源包访问器。这是一个已知限制,已在 issue #6456 中跟踪。
如果目标产品(例如库)不支持资源,Tuist 会将资源包含在产品类型为 bundle 的目标中,以确保其被纳入最终产品,并且接口指向正确的包。这些生成的包会自动标记为 tuist:synthesized,并继承其父目标的所有标签,使你能够在 缓存配置中针对它们。
资源访问器#
资源通过字符串形式的名称和扩展名进行标识。这并不是理想的做法,因为这些错误无法在编译时被捕获,可能会导致发布版本崩溃。为了防止这种情况,Tuist 在项目生成过程中集成了 SwiftGen,以生成访问资源的接口。借此,你可以放心地访问资源,并利用编译器捕获任何问题。
Tuist 默认包含用于为以下资源类型生成访问器的 模板:
| 资源类型 | 生成的文件 |
|---|---|
| 图片和颜色 | Assets+{Target}.swift |
| 字符串 | Strings+{Target}.swift |
| Plist 文件 | {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()])
你可以查看 此示例,了解如何使用自定义模板为资源生成访问器。