Xcode配置

SwiftLint 的安装与使用

SwiftLint

SwiftLint是一个强制使用者按照Github的Swift编码规范指南来开发的一种工具,它会将所有不符合Swift规范的代码全部用warning标注出来,一些严重的违背规则的代码甚至让它无法通过编译(江山一片红),想想是不是就很刺激呢?


为什么需要SwiftLint?

  • 代码风格规范统一
  • 防止低效代码、冗余代码
  • 防止出现可见的明显BUG

SwiftLint安装

全局安装

  • 全局安装非常简单,首先我们需要通过brew命令安装SwiftLint
brew install swiftlint
  • 然后Xode中添加编译脚本
if which swiftlint >/dev/null; then
swiftlint
#echo "skip"
else
echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi
  • 大功告成,就可以编译啦,之后每次安装只需要给工程添加脚本就可以了。
提示了好多代码的警告

局部安装

  • 除了全局安装,我们也可以通过CocoaPods进行安装。在Podfile上添加相关的依赖。
pod 'SwiftLint'
  • 然后跟全局方法一样,在Run Script中添加命令,但是内容有些许的不同。
"${PODS_ROOT}/SwiftLint/swiftlint"

使用配置

在给项目初次接入SwiftLint的时候,你可能会被下面这样的情景给吓到。

但是呢,不用慌,我们可以看一下这是什么情况。仔细观察一番之后,我们会发现,绝大多数的Warning都是这个原因。

WTF?我这一行哪里有空格符?简直就是冤枉啊!但其实是这样的,虽然看起来好像没有空格符,但是在换行符之间不应该掺杂制表符,也就是说你实际的代码是这样的:

\n \tab \n

那么我们该怎么来消除这些Warning呢?

首先,我们要确保,以后我们所码的代码不再出现这样的格式,所以我们需要把Text Editing里面的Including whitespace-only lines勾选上

这样可以保证我们今后的换行不再出现制表符的警告,然后,我们就需要处理现有的代码。现有的代码,少说也有几万行,手动改不是要累死人?这个时候就轮到SwiftLint的命令行出场了

我们将目录切换到工程的根目录之下,然后敲击如下命令:

swiftlint autocorrect

然后我们就会发现,所有的空格符Warning都消失了。这都得益于我们刚刚所进行的命令行操作,它会将已知的能够自动修复的Error和Warning都自动修复,大大的减轻了我们的工作量。

但是又出现了一个问题,在项目的根目录之下执行自动纠正,SwiftLint会将Pods文件夹中的Swift文件也一起纠正了,第三方的框架原则上能不动就不动,那么我们该怎么办呢?

这个时候就需要.swiftlint.yml文件了。那么这是一个什么文件呢?在使用SwiftLint的时候,很多时候我们会碰到一些自定义的规则需求,这个时候就需要.swiftlint.yml来解决问题了。


.swiftlint.yml

所谓的.swiftlint.yml其实就是SwiftLint的一个配置文件,我们可以通过这个配置文件来修改约束的规则,以此达到自定义的效果。一般的配置文件大概长这个样子:

下面我们来认识一下主要的几个配置选项,在此之前我们先要了解一下SwiftLint中的一个概念rules,所谓的rules就是一个一个的风格规则,比如冒号的规则,空格符的规则,类型名的规则等等。截止目前,SwiftLint一共支持75种规则,如果你感兴趣,可以在Source/SwiftLintFramework/Rules 中看到所有规则的实现。或者你也可以在终端输入swiftlint rules来查看当前的规则信息

  • disabled_rules
disabled_rules: # 禁用指定的规则
  - file_length
  - ...
  • opt_in_rules
opt_in_rules: # 启用指定的规则
  - file_length
  - ...
  • whitelist_rules
whitelist_rules: # 规则的白名单,但是不能和上面两个规则一起使用

  - file_length 

  - ...
  • included
included: # 你所希望Lint检索的路径,SwiftLint会扫描该路径下的所有.swift后缀的文件
  - ../
  • excluded
excluded: # 你所希望不要检索的路径,SwiftLint会无视掉该路径下的文件 比如忽略引入的第三方库Pods

  - Pods
  • 风格规则
// 由于风格规则太多了,这里不一一列举,但是用法都是大致相同的
force_cast: [warning | error] 当出现强制类型转换的时候是提示Error还是Warning

type_body_length:
  - 300 # 当超过300行的时候飚黄
  - 400 # 当超过400行的时候飚红
  • 配置文件的嵌套

值得一提的是,在我们使用配置文件的时候,SwiftLint会默认将所指定的文件目录递归的扫描下去的。如果扫描过程中,在子目录下发现了一个新的.swiftlint.yml文件,那么子目录下的规则就会改为新的配置规则。


尝试创建一个配置文件吧

  • 首先需要在项目的根目录下新建一个名为 .swiftlint.yml 的配置文件
  • 打开终端, cd 到项目根目录下
  • 输入: touch .swiftlint.yml
  • 执行完该命令后, 在文件夹中你可能找不到该yml格式文件,那是因为文件被隐藏了
  • 关于隐藏/显示隐藏文件(命令一样): command + shift + .
  • 下面我们来认识一下主要的几个配置选项

官方示例代码

disabled_rules: # 执行时排除掉的规则
  - colon
  - comma
  - control_statement
opt_in_rules: # 一些规则仅仅是可选的
  - empty_count
  - missing_docs
  # 可以通过执行如下指令来查找所有可用的规则:
  # swiftlint rules
included: # 执行 linting 时包含的路径。如果出现这个 `--path` 会被忽略。
  - Source
excluded: # 执行 linting 时忽略的路径。 优先级比 `included` 更高。
  - Carthage
  - Pods
  - Source/ExcludedFolder
  - Source/ExcludedFile.swift

# 可配置的规则可以通过这个配置文件来自定义
# 二进制规则可以设置他们的严格程度
force_cast: warning # 隐式
force_try:
  severity: warning # 显式
# 同时有警告和错误等级的规则,可以只设置它的警告等级
# 隐式
line_length: 110
# 可以通过一个数组同时进行隐式设置
type_body_length:
  - 300 # warning
  - 400 # error
# 或者也可以同时进行显式设置
file_length:
  warning: 500
  error: 1200
# 命名规则可以设置最小长度和最大程度的警告/错误
# 此外它们也可以设置排除在外的名字
type_name:
  min_length: 4 # 只是警告
  max_length: # 警告和错误
    warning: 40
    error: 50
  excluded: iPhone # 排除某个名字
variable_name:
  min_length: # 只有最小长度
    error: 4 # 只有错误
  excluded: # 排除某些名字
    - id
    - URL
    - GlobalAPIKey
reporter: "xcode" # 报告类型 (xcode, json, csv, checkstyle)

常用的规则修改项(简单模板)

excluded:  # 执行 linting 时忽略的路径。 优先级比 `included` 更高。
  - Pods

disabled_rules: # 执行时排除掉的规则
  - identifier_name    # 命名规则必须按照驼峰原则,与后台传的Json字段命名冲突,建议排除掉
  - trailing_whitespace   # 每一个空行不能有空格,会与Xcode换行后自动对齐生成的空格冲突,建议排除掉

force_cast: warning # 类型判断
force_try: warning # try语句判断

cyclomatic_complexity: 20 #代码复杂度,默认为10

line_length:  # 单行代码长度,默认error 120
  warning: 120
  error: 200

file_length:  # 文件长度
  warning: 500
  error: 1200

function_body_length: # 函数体长度
  warning: 100
  error: 300