【Swift】SwiftLint(静的解析ツール)の導入と使い方!アプリの中身をチェック
この記事からわかること
- Swiftで使える静的解析ツールとは?
- SwiftLintの使い方
- アプリの中身を自動でチェックする方法
- .swiftlint.ymlの書き方
- Fastlaneでの実行方法
- Command PhaseScriptExecution failed with a nonzero exit codeの解決法
index
[open]
\ アプリをリリースしました /
環境
- Xcode:16.3
- iOS:18.5
- Swift:5.9
- Mac M1:Sequoia 15.4
静的解析ツールとは?
「静的解析ツール」とはプログラムが記法や規約に則って記述されているかを自動で解析するためのツールです。これを使用することでルールに準じていないコードを特定でき、修正箇所を簡単に識別できるようになります。
プログラムが一定のルールに則って記述されることで冗長なコードのリファクタリングによるコンパイル時間の短縮や可動性向上による複雑性の緩和と保守しやすいコードを保つことができます。
Android
SwiftLintとは?
SwiftLintはSwiftで使用できる静的解析ツールです。チェックできる項目は多く、インデントやスペース、変数の命名などなかなか人では気づきにくい部分もツールを使用することで簡単に識別することが可能です。
またSwiftLintではチェックするファイル自体や細かいルールもカスタマイズすることができるようになっています。
導入方法
SwiftLintはHomebrewかCocoa Podsを使用して導入することが可能です。
Homebrewでインストール
おすすめ記事:【Mac】Homebrewインストール方法!
HomebrewはMacOS(及びLinux)のパッケージ管理システムです。ターミナルからSwiftLintを使用するためにコマンドラインでXcodeが使用できるかを確認しておきます。以下コマンドでバージョンが返ってくるか試しておきます。
$ xcode-select --version
xcode-select version 2409.
問題なければSwiftLintをインストールします。
$ brew install swiftlint
Cocoa Podsでインストール
おすすめ記事:【Swift UI】CocoaPodsのインストール方法と使い方
Cocoa PodsはObjective-CまたはSwiftのライブラリ管理ツールです。インストール方法は他のライブラリと変わらず以下の文を「PodFile」に書き込んでpod installを実行するだけです。
pod 'SwiftLint'
$ pod install
静的解析の使い方と実行方法
SwiftLintを実行する方法はいくつかありますが、今回はXcode内からRun Scriptに組み込む形で実行させるようにしていきます。これでアプリをビルドした際に自動で実行されます。
おすすめ記事:【Swift/Xcode】Run Scriptの設定方法!ビルド時に処理を実行する
まずはXcodeから「TARGET」>「Build Phases」>「Run Script」をクリックします。もしなければ上部の「+」をクリックし「New Run Script Phase」で追加してください。
追加できたらコードブロックの中に以下を書き込みます。swiftlintコマンドを実行することで静的解析が実行されるようになっています。そのためターミナルなどから実行したい場合はswiftlintを実行すればOKです。
Homebrew
XcodeのRun Scriptに記述する際は/opt/homebrew/bin/swiftlintのように記述しないと期待通りに動作しませんでした。
if [ -f /opt/homebrew/bin/swiftlint ]; then
/opt/homebrew/bin/swiftlint
else
echo "⚠️⚠️⚠️ Warning: SwiftLintが未インストール⚠️⚠️⚠️"
fi
Cocoa Pods
if which "${PODS_ROOT}/SwiftLint/swiftlint" >/dev/null; then
${PODS_ROOT}/SwiftLint/swiftlint
else
echo "⚠️⚠️⚠️ Warning: SwiftLintが未インストール⚠️⚠️⚠️"
fi
「Based on dependency analysis」のチェックは外しておいてください。
あとはプロジェクトをビルド(Cmd + B)すれば自動でSwiftLintが働きコードをチェックしてくれます。すると以下のようにエラーや警告がたくさん表示されます。デフォルトのルールは結構厳しめなので良きルールに改変して使用してください。
エラーや警告を自動修正する
SwiftLintを使用して出たエラーや警告の一部はSwiftLintの自動修正機能を使用することで解消することができる場合があります。コマンドで--fix --formatを実行すればインテントや冗長な初期値、isEmptyの使用などを自動でプロジェクト全体(※)を修正してくれます。
$ swiftlint --fix --format
※ 全体と記述しましたが後述している「.swiftlint.yml」でexcludedしているファイルは除外されます。
特定のファイルにのみ自動整形を実行したい場合はファイルパスを指定すればOKです。
$ swiftlint --fix --format {ファイルパス}
またフォーマッターとしてSwiftFormatというツールもあるので気になる方は以下を参考にしてください。
おすすめ記事:【Swift】SwiftFormatの導入と使い方!コードを自動で修正する
.swiftlint.yml:規約を設定する
SwiftLintのルールを設定するにはプロジェクトの直下に.swiftlint.ymlを作成し、適切なルールを記述しておく必要があります。細かいルールの構築方法は以下の公式サイトを確認してください。
公式リファレンス:SwiftLintCore Reference Rule Directory Reference
以下は公式に記載されていたサンプルをそのまま組み込んだところCommand PhaseScriptExecution failed with a nonzero exit codeというエラーが出たので少し修正し、コメント日本語にしたものです。
# デフォルトでは、SwiftLint は適切なデフォルトルールセットを使用します。以下で調整可能です。
disabled_rules: # デフォルトで有効になっているルールのうち、除外したいルールを指定
- colon # コロンのスタイルチェックを無効化
- comma # カンマのスタイルチェックを無効化
- control_statement # if などの制御文の書き方チェックを無効化
opt_in_rules: # デフォルトでは無効になっているルール。使用するには明示的に opt-in が必要
- empty_count # `.count == 0` の代わりに `.isEmpty` を使うことを推奨するルール
# 利用可能なすべてのルールは `swiftlint rules` コマンドで確認できます
# 代わりに、使用するすべてのルールを明示的に指定する方法もあります(以下のオプションのコメントを外す)
# only_rules: # `disabled_rules` と `opt_in_rules` はこの設定を使う場合は削除してください
# - empty_parameters
# - vertical_whitespace
analyzer_rules: # `swiftlint analyze` 実行時に適用されるルール
- explicit_self # 明示的な self の使用を推奨
## 以下をコメントアウトしました
#included: # lint 対象とするパス(大文字小文字を区別)。これを指定すると `--path` は無視される
# - Source
excluded: # lint の対象外とするパス(大文字小文字を区別)。`included` より優先されます
- Carthage
- Pods
- Source/ExcludedFolder
- Source/ExcludedFile.swift
- Source/*/ExcludedFile.swift # ワイルドカードでファイルを除外
# true の場合、lint 対象ファイルが見つからなくても SwiftLint は失敗しません
allow_zero_lintable_files: false
# 設定可能なルールのカスタマイズ
# バイナリルールは severity(警告レベル)を設定できます
force_cast: warning # `as!` の強制キャストに対して警告
force_try:
severity: warning # `try!` の強制使用に対して警告
# 警告とエラーのレベルを持つルールは、警告レベルのみを設定することも可能
line_length: 110 # 1行の最大文字数。これを超えると警告
# 警告とエラーの両方を設定する場合(配列で設定)
type_body_length:
- 300 # 警告レベル
- 400 # エラーレベル
# 警告とエラーを明示的に設定する場合
file_length:
warning: 500 # ファイル行数が 500 行で警告
error: 1200 # ファイル行数が 1200 行でエラー
# 命名規則ルールの設定:min/max 長さの警告・エラー閾値、除外対象など
type_name:
min_length: 4 # 最小長さに対する警告
max_length:
warning: 40
error: 50
excluded: iPhone # 除外する型名
allowed_symbols: ["_"] # 型名に許可される記号
identifier_name:
min_length:
error: 4 # 最小長さに満たない識別子に対してエラー
excluded:
- id
- URL
- GlobalAPIKey # 特定の識別子を除外
# エラー・警告の出力形式を指定(例: xcode, json, markdown など)
reporter: "xcode"
コード内の一部でルールを無効化する
全体には適用しているルールを特定のファイルやコードでのみ許容させたい場合に,ファイルやコード単位でルールを無効化することが可能です。無効化するためにはコードのファイル内にコメントする形で記述します。disableで無効化を始め、指定したルールのenableがある箇所まで無効化します。enableの記載がない場合はファイルの終わりまで適応されます。
// swiftlint:disable <rule1> [<rule2> <rule3> ...]
// ... 無効にしたいコード ...
// swiftlint:enable <rule1> [<rule2> <rule3> ...]
例えばline_lengthとidentifier_nameを無視させる場合は以下のようになります。
// swiftlint:disable line_length identifier_name
let A = "短すぎる変数名かつ長すぎる文字列"
// swiftlint:enable line_length identifier_name
1行だけ無効したい場合はswiftlint:disable:thisかswiftlint:disable:nextを使用します。thisならコードの行に、nextならコメントを記載した次のコードが無効化されます。
let value = value as! String // swiftlint:disable:this force_cast
// swiftlint:disable:next force_cast
let key = key as! String
Fastlaneを使用して実行する
Fastlane経由でSwiftLintを使用できるようになっています。使い方は簡単でswiftlintアクションに適切な引数を渡すだけです。
swiftlint(
mode: :lint, # SwiftLint の実行モード(:lint = 通常の検査, :autocorrect = 自動修正)
# Homebrewでインストール済みならパス指定は不要
executable: "Pods/SwiftLint/swiftlint", # SwiftLint 実行ファイルのパス(CocoaPods で導入した場合は必須)
path: "/path/to/lint", # 検査対象のディレクトリパス(省略可能)
output_file: "swiftlint.result.json", # 出力結果を保存するファイルパス(省略可能)
reporter: "json", # 出力形式(json, xcode, html, github-actions など)
config_file: ".swiftlint-ci.yml", # 使用する設定ファイルのパス(省略可能。デフォルトは .swiftlint.yml)
files: [ # 特定のファイルのみを検査したい場合に指定(省略可能)
"AppDelegate.swift",
"path/to/project/Model.swift"
],
ignore_exit_status: true, # SwiftLint がエラー終了しても fastlane を停止させない(デフォルト: false)
quiet: true, # 'Linting 開始' や '完了' などのログ出力を抑制する(デフォルト: false)
strict: true # 警告もエラーとして扱い、処理を失敗と見なす(デフォルト: false)
)
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。







