所有文章已搬遷到個人站點:me.harley-xk.studio,歡迎訪問留言
原由
最近跟著公司大佬在做 Laravel 后端開發(fā),要求使用 php lint 進行代碼規(guī)范檢查之后才能 push 代碼,保證所有人寫出風格統(tǒng)一的代碼,方便后期的維護和 Review,于是開始往老本行上反思。
想想自己寫了五六年的 iOS ,雖然自認代碼還是寫的很規(guī)整的,但是寫 high 了之后還是會忽略很多細節(jié)上的東西,雖說無傷大雅,但是軟件開發(fā)作為一門工程性質(zhì)的東東,始終覺得規(guī)范化是一件很重要的事情。
在之前的公司也曾經(jīng)在 iOS 組內(nèi)部推行過代碼規(guī)范的實施,但那時候還只是停留在弄個 Word 文檔,把各條規(guī)范列一列,然后開個小會普及下的程度上?,F(xiàn)在接觸了不少其他開發(fā)領(lǐng)域的東西,越來越覺得對于開發(fā)者來說提高視角去了解各個方面是多么重要的一件事情。不同領(lǐng)域的經(jīng)驗、做事的方式、思路,都可以相互借鑒與融合。
于是開始尋找在 iOS 下實行類似方案的可能性。說來也巧,最近在看 iOS 相關(guān)資料的時候發(fā)現(xiàn)了 SwiftLint 這玩意兒,遂打算來實踐下。
SwiftLint 是啥?
SwiftLint 是 Realm 推出的一款 Swift 代碼規(guī)范檢查工具,Realm 就不用介紹了,他們家推出的移動端跨平臺數(shù)據(jù)庫在業(yè)內(nèi)的名氣還是很大的,就算沒有用過,相信大多數(shù)人也是聽過的。
SwiftLint 基于 Github 公布的 Swift 代碼規(guī)范進行代碼檢查,并且能夠很好的和 Xcode 整合。配置好所有的設(shè)置之后,在 Xcode 中執(zhí)行編譯時,SwiftLint 會自動運行檢查,不符合規(guī)范的代碼會通過警告或者 error 的形式指示出來,并且擁有豐富的配置項,可以進行大量的自定義,相當方便。
安裝配置
SwiftLint 有多種不同的安裝方式,可以根據(jù)自己的喜好選擇。
使用 Homebrew 安裝
Homebrew 是 macOS 自帶的包管理工具,使用這種方式安裝也是最簡單的:
brew install swiftlint
使用 CocoaPods 安裝
通過 CocoaPods 安裝同樣很簡單,只需要在 Podfile 中添加依賴:
pod 'SwiftLint'
之后執(zhí)行 pod install 就可以自動安裝了,這種方式會將 SwiftLint 安裝到項目的 Pods/ 目錄下。如果你想要針對不同的項目使用不同的 SwiftLint 版本,這是一種很好的解決方案(Homebrew 會自動安裝最新版本)。
需要注意的是使用這種方案會將整個 ** SwiftLint** 以及他的依賴包的完整資源文件都安裝到 Pods/ 目錄中去,所以在使用版本管理工具比如 git 時要注意設(shè)置忽略相關(guān)目錄。
使用安裝包
SwiftLint 還支持使用 pkg 安裝包進行安裝,在官方的 Github 頁面可以找到最新發(fā)布的安裝包。
編譯源代碼
SwiftLint 完全使用 Swift 開發(fā),并且它是基于 MIT License 開源的,所以你可以下載它的源代碼,然后通過以下命令編譯安裝:
git submodule update --init --recursive; make install
安裝完成
等待安裝完成,輸入 swiftlint help 可以查看所有可用的命令:
? ~ swiftlint help
Available commands:
autocorrect Automatically correct warnings and errors
help Display general or command-specific help
lint Print lint warnings and errors (default command)
rules Display the list of rules and their identifiers
version Display the current version of SwiftLint
到此 SwiftLint 就安裝完成了
配置 Xcode
接下來需要在工程中配置相關(guān)編譯選項,才能使 SwiftLint 在 Xcode 中運行起來。配置也很簡單,只需要在 Xcode 的 Build Phases 中新建一個 Run Script Phase 配置項,在里面添加如下代碼:
if which swiftlint >/dev/null; then
swiftlint
else
echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi
如圖所示:
[圖片上傳失敗...(image-933261-1580636760609)]
如果是通過 CocoaPods 安裝的 SwiftLint 需要將 swiftlint 替換為 CocoaPods 中的路徑: "${PODS_ROOT}/SwiftLint/swiftlint"。
這里其實是設(shè)置了一個自動編譯腳本,每次運行編譯都會自動執(zhí)行這個腳本,如果正確安裝了 SwiftLint,就會執(zhí)行 SwiftLint 中的代碼規(guī)范檢查,如果沒有安裝,腳本會拋出一個沒有安裝 SwiftLint 并提示下載的警告,方便提醒團隊團隊中沒有安裝的成員。
當然,你也可以設(shè)置為強制要求安裝,這時如果沒有安裝則無法通過編譯。只需要在腳本中 echo "warning: ..." 之后添加一行代碼:exit 1,這樣一來,如果沒有安裝 SwiftLint,編譯時會直接拋出一個編譯錯誤而非警告,提示需要安裝 SwiftLint。
到此配置就完成了,是不是很簡單。
自定義配置
現(xiàn)在編譯一下項目看看,是不是很可怕??:

不要被 999+ 嚇到了,仔細看一下具體的錯誤,會發(fā)現(xiàn)好多都是第三方庫的代碼規(guī)范問題,而且好多問題的級別被設(shè)置成為了 error
這樣子可不行,第三方庫的代碼規(guī)范問題不能讓我們自己的項目來背鍋,接下來需要做一些配置,讓 SwiftLint 在做代碼規(guī)范檢查的時候自動忽略 CocoaPods、Carthage 等包管理器引入的第三方庫(當然,手動導入的第三方庫也能設(shè)置忽略)
首先需要在項目的根目錄下新建一個名為 .swiftlint.yml 的配置文件,輸入如下內(nèi)容:
excluded:
- Pods
excluded 配置項用來設(shè)置忽略代碼規(guī)范檢查的路徑,可以指定整個文件夾,也可以指定精確路徑下的文件,通過 - xxxx 的形式列在下面就可以了,比如如果你的項目使用 Carthage 管理第三方庫的話,可以將 Carthage 目錄添加到忽略列表:
excluded:
- Pods
- Carthage
保存之后再來編譯下,少了很多編譯錯誤了,至少第三方庫的編譯錯誤都被干掉了,oh yeah~

不過錯誤和警告依然很多,繼續(xù)往下看,發(fā)現(xiàn)大量的
trailing_whitespace 的警告,這個是之前寫代碼不注意留下的,在空行中包含了空格,雖然肉眼看不出來,但是 SwiftLint 火眼金睛啊。
你可以選擇更正所有這些不規(guī)范的問題,不過如果這個這個項目是遺留下來的老項目,可能存在大量類似的問題,手動更正這些問題需要相當多的精力,這時候可以選擇開啟忽略這類問題,只需要在
.swiftlint.yml 文件中加入如下代碼:
disabled_rules:
- trailing_whitespace
再次編譯,發(fā)現(xiàn) trailing_whitespace 的問題已經(jīng)不再提示了,你可以用同樣的方法配置忽略特定的規(guī)則。
其他規(guī)則
Xcode自動生成的代碼經(jīng)常包含大段的注視,我們經(jīng)常會選擇保留這些注釋。不過 SwiftLint 有一個 line_length 的規(guī)則,默認是會檢查注釋的長度的,可以在 .swiftlint.yml 中設(shè)置忽略檢查注釋的長度:
line_length:
warning: 110
ignores_function_declarations: true
ignores_comments: true
這段代碼設(shè)置了 line_length 的檢查規(guī)則:
warning: 110 表示單行字符數(shù)超過 110 時拋出警告,你也可以設(shè)置為其他的值。
ignores_function_declarations 表示是否忽略檢查函數(shù)定義的長度
ignores_comments 設(shè)置是否忽略檢查注釋的長度
當然,你也可以在 disabled_rules 中設(shè)置忽略單行長度規(guī)則
這里有所有目前已經(jīng)實現(xiàn)了的規(guī)則。你也可以實現(xiàn)自己的規(guī)則,然后給他們發(fā) Pull requests。
本文的最后附上了我自己的 .swiftlint.yml 文件,你可以在 SwiftLint 的官方文檔找到更多關(guān)于自定義規(guī)則的說明。
設(shè)置完所有配置之后,再次編譯代碼,之后就可以根據(jù)錯誤提示去更正不規(guī)范的代碼了。
.swiftlint.yml 的嵌套
.swiftlint.yml 配置文件支持嵌套,因此
- 你可以給每個文件夾下的代碼單獨指定不同的規(guī)則設(shè)置
- 每個文件會匹配距離自己層級最近的父文件夾中的配置文件
- 嵌套的配置文件中的
excluded和included配置會被忽略
結(jié)語
終于寫完了第一篇技術(shù)博客,深感寫文章的不易,希望能保持下去。
這篇文章是我在初步研究了 SwiftLint 之后寫的,一定有很多謬誤和不足之處,各位輕噴- -
<a name="SwiftLint">.swiftlint.yml</a>
disabled_rules: # rule identifiers to exclude from running
- force_cast
- trailing_whitespace
- cyclomatic_complexity
- unused_closure_parameter
# - colon
# - comma
# - control_statement
# opt_in_rules: # some rules are only opt-in
# - empty_count
# - missing_docs
# # Find all the available rules by running:
# # swiftlint rules
# included: # paths to include during linting. `--path` is ignored if present.
# - Docs.M/*/*.swift
excluded: # paths to ignore during linting. Takes precedence over `included`.
- Carthage
- Pods
# - Source/ExcludedFolder
# - Source/ExcludedFile.swift
# configurable rules can be customized from this configuration file
# binary rules can set their severity level
# force_cast: warning # implicitly
force_try:
severity: warning # explicitly
# rules that have both warning and error levels, can set just the warning level
# implicitly
line_length:
warning: 200
ignores_function_declarations: true
ignores_comments: true
# they can set both implicitly with an array
type_body_length:
- 300 # warning
- 400 # error
# or they can set both explicitly
file_length:
warning: 500
error: 1200
# naming rules can set warnings/errors for min_length and max_length
# additionally they can set excluded names
# type_name:
# min_length: 4 # only warning
# max_length: # warning and error
# warning: 40
# error: 50
# excluded: iPhone # excluded via string
identifier_name:
min_length: # only min_length
error: 3 # only error
excluded: # excluded via string array
- id
# - URL
# - GlobalAPIKey
reporter: "xcode" # reporter type (xcode, json, csv, checkstyle, junit, html, emoji)