- 开发工具
- 代码生成
- CLI
- 原生移动
【免费下载链接】R.swift
Strong typed, autocompleted resources like images, fonts and segues in Swift projects
本文是 R.swift 资源控制机制的实战指南,聚焦两大核心能力:通过.rswiftignore文件精确排除项目中的问题资源,以及通过--generators参数只运行指定类型的资源生成器。读完本文,你将掌握.rswiftignore的完整语法(通配符、注释、!显式包含)、自定义 ignore 文件路径的 CLI 用法,以及如何在 Build Phase 中按需裁剪R.image、R.string、R.nib等生成结构,让 R.swift 的资源发现过程完全处于你的掌控之下。
为什么需要忽略资源
R.swift 会自动扫描项目中的资源(图片、字体、Storyboard、Strings 等)并为它们生成强类型的R结构。绝大多数情况下,自动发现开箱即用;但在少数情况下,某个文件可能给解析过程带来问题——例如文件命名中包含 Swift 关键字、文件格式无法被解析器识别、或者某些资源根本不想暴露在生成的 API 中。此时就需要忽略机制来"隔离"这些文件。
除了忽略单个资源文件,R.swift 还允许只运行部分生成器,从而跳过不需要的R.something结构,从源头减少生成代码的体积。
工作机制:.rswiftignore文件
在项目的 source root(源码根目录)下创建一个名为.rswiftignore的文件,R.swift 会自动发现并读取它。文件格式与.gitignore的模式语法 几乎相同:
*和**通配符均受支持;- 以
#开头的行是注释; - 以
!开头的模式用于显式包含某个或某类文件(即使它们被其他规则全局忽略了)。
注意:所有模式都是相对于
.rswiftignore文件所在路径的文件路径,而不是相对于项目根目录或当前工作目录。
完整示例
官方文档给出的标准配置示例:
# Ignore a specific font file fonts/myspecialfont.ttf # Ignore all tiff and tif files in the images folder images/*.tif images/*.tiff # Ignore all strings files wherever they are **/*.strings # Ignore all files containing '.ignore.' **/*.ignore.* # Explicitly include a single file !keepme.ignore.png # Explicitly include all files containing '.keepme.' !**/*.keepme.*逐条解读:
fonts/myspecialfont.ttf:精确忽略单个字体文件,路径相对.rswiftignore所在目录;images/*.tif、images/*.tiff:匹配images目录下的所有 tif/tiff 图片,注意*不跨目录层级;**/*.strings:**递归匹配任意层级的子目录,忽略项目中所有.strings文件;**/*.ignore.*:忽略文件名中包含.ignore.的所有文件(不管在哪个目录层级);!keepme.ignore.png:显式包含单个文件,即使它匹配了上面的**/*.ignore.*规则;!**/*.keepme.*:显式包含所有文件名含.keepme.的文件。
规则匹配的底层逻辑
从源码看,IgnoreFile的解析与匹配逻辑非常清晰。读取文件后按换行拆分为候选模式,然后分两条流水线处理(IgnoreFile.swift):
- 忽略模式:过滤掉空行、注释行和
!开头行,剩余模式展开成具体的文件 URL 列表,存入ignoredURLs; - 显式包含模式:只取
!开头的行,去掉首字符后同样展开成 URL 列表,存入explicitlyIncludedURLs。
最终的匹配判定(IgnoreFile.swift)是:
public func matches(url: URL) -> Bool { return ignoredURLs.contains(url) && !explicitlyIncludedURLs.contains(url) }即先看是否被忽略规则命中,再看是否被显式包含规则豁免——两者同时成立时文件不被忽略。这保证了!规则具有比普通忽略规则更高的优先级。
判断哪些行算有效模式(IgnoreFile.swift)时,源码会先对每行做空白修剪:空行被丢弃;修剪后首字符为#的视为注释;首字符为!的视为显式包含模式。
模式展开底层依赖仓库内置的Glob实现(Glob.swift),默认采用GlobBehaviorBashV4行为(Glob.swift),即支持 globstar(**递归匹配)并包含 globstar 根目录下的文件。值得注意的是,Glob 默认黑名单了node_modules和Pods两个目录(Glob.swift),因此即使模式写得比较宽泛,这两个目录也不会被意外扫描。
忽略发生在哪个阶段
忽略过滤不是在生成代码时才执行,而是在资源解析阶段就完成了。在ProjectResources.parseXcodeproj中,从 Xcode 工程提取出所有资源路径后,会立即用 ignore 文件做一次过滤(ProjectResources.swift):
let urls = paths .map { $0.url(with: sourceTreeURLs.url(for:)) } .filter { !ignoreFile.matches(url: $0) }也就是说,被忽略的资源根本不会进入后续的图片、字体、Strings 等解析器,自然也就不会出现在生成的R.generated.swift中。如果.rswiftignore文件缺失或读取失败,IgnoreFile会退化为一个空的 ignore 实例(不忽略任何文件),保证默认行为不受影响(ProjectResources.swift)。
仓库中的实证:IgnoreTests
官方示例工程Examples/ResourceApp中实际放置了Keep.dont.ignoreme.png、icon.ignoreme.png、hand.ignoreme.png、ExplicitInclude.ignoreme.png等文件名含.ignore.的资源,用于验证忽略规则。测试文件 IgnoreTests.swift 中:
func testExplicitInclude() { XCTAssertNotNil(R.image.keepDontIgnoreme()) }验证了Keep.dont.ignoreme.png通过!显式包含规则被保留并生成为R.image.keepDontIgnoreme(),而其他.ignoreme文件被成功过滤掉。这直接印证了"忽略规则生效、!包含规则生效"两条路径在真实工程中的行为。
自定义 ignore 文件位置
默认情况下.rswiftignore必须位于 source root。如果你希望把 ignore 文件放在其他位置、或者使用不同的文件名,可以通过--rswiftignore标志显式指定路径:
rswift generate --rswiftignore config/ignore.list /path/to/R.generated.swift从源码看,命令行选项的默认值正是.rswiftignore(App.swift),解析时会基于sourceRootURL拼接出最终的 ignore 文件 URL(App.swift):
let rswiftIgnoreURL = sourceTreeURLs.sourceRootURL .appendingPathComponent(globals.rswiftignore, isDirectory: false)因此当你用--rswiftignore传入自定义路径时,该路径同样会相对于 source root 解析。
只运行特定生成器(排除 R.something)
默认情况下,R.swift 会运行全部生成器,为图片、nib、strings 等所有资源类型生成结构。在某些场景下(比如只想生成图片和字符串),可以通过--generators标志只运行指定类型:
rswift generate --generators image,string /path/to/R.generated.swift多个生成器名称用逗号分隔。该标志通常加在 Build Phase 中调用 rswift 的命令行里,例如在 Xcode 的 Run Script 阶段配置:
可用生成器完整清单
官方文档列出的可用生成器如下:
| 生成器名称 | 对应生成的 R 结构 |
|---|---|
image | R.image,图片资源 |
string | R.string,本地化字符串表 |
color | R.color,颜色资源 |
file | R.file,普通文件资源 |
font | R.font,字体资源 |
nib | R.nib,nib/xib 视图 |
segue | R.segue,segue 标识符 |
storyboard | R.storyboard,storyboard 引用 |
reuseIdentifier | R.reuseIdentifier,复用标识符 |
entitlements | R.entitlements,代码签名 entitlements |
info | R.info,Info.plist 内容 |
id | R.id,无障碍标识符(accessibility identifier) |
需要补充说明的是,从源码看ResourceType枚举(ProjectResources.swift)实际定义了 14 种类型,除了上表 12 种之外还包括:
data:资产目录(Asset Catalog)中的 Data 资源,对应R.data;project:工程级信息结构(包含开发语言与已知资源标签等)。
这两个生成器在当前仓库的 CLI 中同样可用,属于文档未列全而源码已实现的能力。
生成器过滤的底层实现
--generators参数的解析很简单:按逗号拆分后映射为ResourceType(App.swift)。当未传入任何生成器时,会回退为运行全部类型(App.swift):
generators: globals.generators.isEmpty ? ResourceType.allCases : globals.generators,真正决定"哪个R.something出现"的逻辑在 RswiftCore.swift:生成器会逐一对每个结构做generators.contains(.xxx)判断,且要求对应解析结果非空才把该结构写进最终的R.generated.swift。例如字符串结构仅在generators.contains(.string)且stringStruct非空时生成。这意味着:
- 未列入
--generators的类型,其解析器不会运行(见 ProjectResources.swift 中各处resourceTypes.contains(...)前置判断),解析开销也被省掉; - 即使类型被列入,若项目中该类型资源为空,对应结构也会被跳过,生成的代码保持精简。
另外注意,font、nib、storyboard三个结构还参与了R结构中validate()方法的生成(RswiftCore.swift):只有当对应生成器开启且结构非空时,validate()中才会加入对应的校验行。
实战建议与常见误区
- 优先用忽略而非删除文件:
.rswiftignore不影响 Xcode 打包,被忽略的资源仍会随 App 分发,只是不进入强类型 API。适用于"文件必须存在但不想暴露"的场景。 !规则必须写在对应忽略规则之后才生效?从源码实现看,IgnoreFile并不区分规则先后顺序——它先把所有忽略模式展开成 URL 列表,再展开所有显式包含模式,匹配时做集合判定。因此!豁免不依赖书写顺序,这一点与部分 gitignore 实现略有差异。- 模式必须相对
.rswiftignore文件:写绝对路径或相对项目根目录的路径都可能匹配不上,这是最常见的踩坑点。 - 利用
--generators收敛生成体积:如果只使用图片和字符串,--generators image,string能让生成的R.generated.swift更小、构建更快,也减少了无关 API 的暴露面。 - 结合 Build Phase 使用:
--generators与--rswiftignore都是 rswift 命令的全局选项(见 App.swift),可以直接拼接到 Build Phase 的 Run Script 中,与 R.swift 的自动发现机制共存。
小结
R.swift 的忽略与生成器定制机制,为资源发现提供了"减法"能力:.rswiftignore以类 gitignore 的语法、相对路径规则和!显式包含语义,在解析阶段精确过滤问题资源;--rswiftignore允许自定义 ignore 文件位置;--generators则从生成阶段按类型裁剪R结构。理解 IgnoreFile.swift 的集合匹配逻辑与 ProjectResources.swift 的解析期过滤流程,你就能在遇到异常资源文件、或希望精简生成 API 时,快速给出可复用的解决方案。
- 开发工具
- 代码生成
- CLI
- 原生移动
【免费下载链接】R.swift
Strong typed, autocompleted resources like images, fonts and segues in Swift projects
相关推荐
Terraform-docs 忽略资源生成指南:精准控制文档输出内容
Terraform docs 忽略资源生成指南:精准控制文档输出内容 痛点:为什么需要忽略资源? 在日常的Terraform模块开发中,我们经常会遇到这样的场景
开发工具文档Kubernetes 2024社区治理演进:3大架构突破与扩展性优化实践
Kubernetes 2024社区治理演进:3大架构突破与扩展性优化实践 Kubernetes社区作为全球最大的开源容器编排平台,在2024年实现了社区治理架构
开源治理文档研发协作Captura缩略图生成并发控制:线程池管理与资源限制
Captura缩略图生成并发控制:线程池管理与资源限制 引言:缩略图生成的性能挑战 在屏幕录制软件Captura中,缩略图生成是提升用户体验的关键功能,它允许用
桌面应用屏幕录制音视频
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考