Skip to content

04编码规范:如何使用SwiftLint统一编码规范?

在软件开发领域有很多有趣且重要的话题,比如使用什么样的系统架构来让代码更容易维护,使用哪些第三方库能提高开发效率,等等。但也有一些话题不仅无趣,还很难得出结论,比如像下面这行变量定义,里面的空格哪个正确?

java
let name: String = "Jake"
let name : String = "Jake"
let name :String = "Jake"
let name: String= "Jake"
let name: String="Jake"

还有代码缩减,到底是用 2 个空格还是 4 个?这就像豆浆到底是喝甜的还是喝咸的一样,并没有标准答案。也因此,出现了许多永无休止的讨论。特别是当新成员所提交的代码风格,与团队其他成员有很大的区别时,往往会出现沟通与协作问题,甚至发生争执而影响工作。此时,团队如果有一套统一的编码规范,那么这样的问题就很容易解决。

除了能促进沟通协作,一套统一的编码规范还能降低代码维护的成本和减少 Bug 的数量。此外,由于规范往往由团队资深开发者指定并不断完善,也有助于其他团队成员快速成长。

既然统一的编码规范由那么多优点,那么我们如何在团队中实施统一编码规范呢?在 iOS 开发领域,使用 SwiftLint 能有效地建立和改进 Swift 项目的编码规范。接下来我就和你聊聊这方面的内容。

安装 SwiftLint

安装 SwiftLint 的方式有很多种,例如使用 Homebrew,Mint,下载 SwiftLint.pkg 安装包等等。但我只推荐 CocoaPods 这一种方法,因为通过 CocoaPods 可以有效地管理 SwiftLint 的版本,从而保证团队内各个成员都能使用一模一样的 SwiftLint 及其编码规范。

通过 CocoaPods 来安装 SwiftLint 非常简单。在 Moments App 项目中,我们在Podfile文件中添加SwiftLintPod 即可。

java
pod 'SwiftLint', '= 0.41.0', configurations: ['Debug']

由于我们只在开发环境下使用 SwiftLint,因此配置了只有Debug的 Build Configuration 才生效。

为了每次编译完都使用 SwiftLint 来检查代码,我们需要在主 App TargetMoments 的 Build Phases 里面添加Run SwiftLint 步骤。然后配置它执行"${PODS_ROOT}/SwiftLint/swiftlint"命令。

这里要注意,由于 SwiftLint 的设计是检查有效的 Swift 代码(编译通过的代码就是有效的代码),我们需要把Run SwiftLint 步骤放在Compile Source步骤之后。否则 SwiftLint 可能会反馈一些错误的结果。

有了上面的配置以后,每次编译程序, SwiftLint 都会自动执行检查,我们可以在 Xcode 上修正这些警告信息来保证编码规范的统一。

例如上面的截图所示,SwiftLint 告诉我们空格的使用不正确。

那么,这些警告信息到底怎样来的呢?我们一起看看.swiftlint.yml文件吧。

.swiftlint.yml 文件

当我们执行 SwiftLint 命令时,它会自动帮我们启动一堆编码规则,并扫描和检查我们的项目。这些规则有comma(逗号前后的空格处理),private_over_fileprivate(优先使用 priviate),force_cast(避免强制转型)等等 。详细规则列表你也可以在SwiftLint 官网找到。

但正如 SwiftLint 的作者所说: "规则存在,但并不意味着你必须用它"。我们需要根据团队自身的情况和成员的统一意见,来决定需要启动和关闭哪些规则。此时,就需要用到 .swiftlint.yml 文件了。

.swiftlint.yml主要用于启动和关闭 SwiftLint 所提供的规则,以及自定义配置与规则。一旦我们有了 .swiftlint.yml 文件以后,SwiftLint 在执行过程中会严格按照该文件的定义来扫描和检查代码。由于 .swiftlint.yml 是一个纯文本文件,我们可以通过 Git 统一管理,这样能保证整个团队在执行 SwiftLint 的时候都会得到一模一样的效果,从而保证了整个团队代码规范的一致性。

规则设置

SwiftLint 提供了disabled_rules,opt_in_rulesonly_rules三种规则设置方法。其中,disabled_rules能帮我们关闭默认生效的规则,而opt_in_rules可以启动默认关闭的规则。

另外,SwiftLint 所提供的每条规则都有一个叫作Enabled by default 的属性来表示该规则是否默认启动。例如class_delegate_protocol规则是默认启动的,而array_init规则是默认关闭的。

java
disabled_rules:
  - class_delegate_protocol
opt_in_rules:
  - array_init

上面的配置表示,关闭默认生效的class_delegate_protocol,并同时启动array_init

虽然使用disabled_rulesopt_in_rules能够完成配置,但我不推荐你使用它们 ,而是用only_rules来定义每条生效的规则。

我们在 Moments App 项目中也使用了only_rules。你可以在拉勾教育的代码仓库找到该 .swiftlint.yml 文件来查看项目启动的所有规则。由于only_rules是 SwiftLint 0.41.0 引入的,如果你需要以前版本,可以使用whitelist_rules来替代。下面是 .swiftlint.yml 文件中的部分规则。

java
only_rules:
  - array_init
  - attributes
  - block_based_kvo
  - class_delegate_protocol
  - closing_brace

通过only_rules,我们可以把每一条规则明确添加到 SwiftLint 里面。这样能保证我们整个团队都使用一致的规则,而不会像使用disabled_rulesopt_in_rules那样,随着 SwiftLint 默认规则的改变,导致最终启动的规则不一样。

自定义配置

在我们配置一条规则的时候,为了符合团队自身的情况,可以修改其默认配置。例如line_length的默认配置是当一行代码多于 120 个字符的时候会报告编译警告,而多于 200 个字符的时候报告编译错误。

来源:SwiftLintFramework Docs

我们可以在 .swiftlint.yml 文件中修改这些配置。

java
line_length: 110
file_length:
  warning: 500
  error: 1200

上述的配置表示我们修改了line_length的配置,当一行代码多于 110 个字符(而不是默认的 120 个字符)时就会报告编译警告。我们也可以同时覆盖编译警告和编译错误的配置,例如把file_length的编译警告改成 500,而编译错误改成 1200。

自定义规则

除了 SwiftLint 所提供的默认规则以外,我们还可以自定义规则。例如在 Moments App 项目中,我就自定义了"不能硬编码字符串"的规则,具体如下:

java
custom_rules:
  no_hardcoded_strings:
    regex: "([A-Za-z]+)"
    match_kinds: string
    message: "Please do not hardcode strings and add them to the appropriate `Localizable.strings` file; a build script compiles all strings into strongly typed resources available through `Generated/Strings.swift`, e.g. `L10n.accessCamera"
    severity: warning

该规则no_hardcoded_strings会通过正则表达式来检查字符串是否进行了硬编码。如果是SwiftLint 会根据我们的自定义规则显示警告信息,如下图所示。

排除扫描文件

默认情况下 SwiftLint 会扫描和检查整个项目的所有代码。因为一些第三方依赖库的源码风格可能和我们团队的风格不一致,为了方便使用第三方依赖库,我们可以用excluded来把它排除在外,避免扫描和检查。示例如下:

java
excluded:
  - Pods

现在我们已经通过配置 .swiftlint.yml 文件来帮助我们统一编码规范了。

总结

在这一讲,我介绍了如何使用 SwiftLint 来统一编码规范。特别是其中的only_rules,我们要使用它来定义需要生效的规则。

此外,在制定编码规范时,我们还需要注意以下几点。

首先,所制定的规范要和业界标准同步,这能让新成员接手代码时,更容易接受而不是反驳。一个建议是,你可以从 SwiftLint 所提供的默认规则开始,毕竟这些规则都是通过许多人沟通和完善下来的,比你独自一人想出来要靠谱得多。

其次,在制定规范时,重点是提高代码的可读性,而不是为了高大上去使用黑魔法或者选择那些不常用功能等。这样可以让团队绝大部分成员更容易理解和遵循这些规范。

最后要强调的是,一套编码规范是需要不断迭代和完善的,我建议团队要定时 Retro(Retrospective,敏捷回顾),讨论和优化这些规范,让得大家都有机会贡献到规范中,增加他的认同感。这种做法在多团队平行开发的环境下特别有效。

思考题:

你所做的团队除了使用 SwiftLint 等工具检查以外,还使用了哪些手段来保证编码规范的统一呢?

请把回答写到下面的留言区哦,下一讲我将介绍如何使用 Fastlane 执行自动化操作。

源码地址:

swiftlint.yml 文件
https://github.com/lagoueduCol/iOS-linyongjian/blob/main/Moments/.swiftlint.yml


[

](https://shenceyun.lagou.com/t/mka)

《大前端高薪训练营》

12 个月打磨,6 个月训练,优秀学员大厂内推,点击报名,高薪有你