1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SwiftFormatでフォーマットを統一しよう(コミット時に自動実行も可能!)

Posted at

はじめに

個人でiOSアプリ開発を行なっている田中幹久です。

SwiftFormatとは

コードをプロジェクト全体で統一できるツールです。
複数人での共同編集では必須の機能だと考えています。
これは手動での実行のほかに、ビルド時での自動実行などもできます。
その中でもコミット時の自動実行の方法も紹介したいと思います。
備忘録も兼ねてこの記事を書きます。

例えば、以下のような場合。

Sample.swift

//サンプル1(修正前)
if [].count == 0 {}

//サンプル2(修正後)
if [].isEmpty {}

このようなケースで、SwiftFormatを実装すると、どちらか一方に統一できます。
他にも、変数名のルールであったり、改行のタイミングなどなど細かくカスタムできます。

実装手順

1. BuildToolsの導入

File>New>Packageから、BuildToolsを追加します。

スクリーンショット 2025-08-23 21.12.07.png

以下のようにAdd toGroupを設定してください。

スクリーンショット 2025-08-23 21.14.52.png

以下のようになれば成功です。

スクリーンショット 2025-08-23 21.15.08.png

BuilrToolsは初期設定のままで良いです。

2. SwiftFormatのインストール

brew install swiftformat

3. SwiftFormatパッケージの導入

SPMで以下のURLをコピペして実装してください。
Add to targetは変更しなくて良いです。

https://github.com/nicklockwood/SwiftFormat.git

4. 必要なファイルの作成

4.1 SwiftFormat設定ファイル

プロジェクトルートに.swiftformatファイルを作成し、以下の内容をコピペしてください。

.swiftformat
# swift-format configuration file
# Rule List: https://github.com/nicklockwood/SwiftFormat/blob/master/Rules.md

# --------------------
# File Options
# --------------------
--swiftversion 5.6
--exclude Pods,Carthage,BuildTools

# --------------------
# Formatting Options
# --------------------

# 複数行の配列や辞書などで、最後のカンマを強制的に削除する
--commas inline

# "0...9" のような範囲演算子の周りにスペースを入れない
--ranges no-space

# 空白に関する設定
--trimwhitespace always

# 引数が複数ある場合、引数ごとに改行する
--wraparguments before-first

# インデントをスペース4つに設定
--indent 4

# --------------------
# Opt-in Rules (有効化するルール)
# --------------------

# import文をアルファベット順にソートする
--sorted-patterns

# .count == 0 を .isEmpty に置換する
--enable isEmpty

# ----------------------------------------------------
# Disabled Rules (デフォルトから無効化しているルール)
# ----------------------------------------------------

--disable enumNamespaces
--disable extensionAccessControl
--disable preferKeyPath
--disable redundantExtensionACL
--disable redundantObjc
--disable redundantReturn
--disable redundantSelf
--disable semicolons          # 行末のセミコロンを自動削除しない
--disable strongOutlets
--disable strongifiedSelf
--disable todos               # FIXME/TODOコメントに関するルールを無効化
--disable typeSugar           # [Int] を Array<Int> に変換しない
--disable unusedArguments     # 未使用の引数に `_` を自動付与しない
--disable void                # () を Void に変換しない
--disable wrapMultilineStatementBraces

4.2 GitHooksディレクトリの作成

次は、コミット時に自動でSwiftFormatを実行する設定です。

mkdir -p GitHooks

4.3 pre-commitフックの作成

GitHooks/pre-commitファイルを作成し、以下の内容をコピペしてください:

#!/bin/sh

# 新プロジェクトへの実装手順
#1. git config --local core.hooksPath GitHooks

# 現在のブランチを取得
CURRENT_BRANCH=$(git branch --show-current)

# mainブランチの場合はスキップ
if [ "$CURRENT_BRANCH" = "main" ]; then
    echo "🔒 mainブランチのため、pre-commitフックをスキップします。"
    exit 0
fi

# Homebrewでインストールしたswiftformatを直接呼び出す
# 'command -v'でコマンドの存在を確認
if ! command -v swiftformat &> /dev/null
then
    echo "⛔️ swiftformatコマンドが見つかりません。"
    echo "   'brew install swiftformat' を実行してインストールしてください。"
    exit 1
fi

echo "✅ SwiftFormatのチェックを実行します..."

# ステージングされたSwiftファイルのみを対象にする
STAGED_SWIFT_FILES=$(git diff --diff-filter=d --staged --name-only | grep -e '\(.*\).swift$')

if [ -z "$STAGED_SWIFT_FILES" ]; then
  echo "Swiftファイルはコミット対象外です。スキップします。"
  exit 0
fi

# まずは--lintでチェックだけ行う
echo "フォーマットをチェック中..."
echo "$STAGED_SWIFT_FILES" | xargs swiftformat --lint

if [ $? -eq 0 ]; then
  echo "✨ 全てのファイルが整形済みです。コミットを完了します。"
  exit 0
fi

# lintでエラーがあった場合、フォーマットを適用してコミットを中断
echo "⚠️ フォーマットの乱れを検出しました。自動修正します..."
echo "$STAGED_SWIFT_FILES" | xargs swiftformat

echo "⛔️ ファイルが自動修正されました。再度 'git add' してコミットし直してください。"
exit 1

4.4 実行権限の付与

以下のコマンドを打たないと実行されません。
プロジェクトのパスで以下のコマンドを実行してください。

chmod +x GitHooks/pre-commit

4.5 GitHooksのパス設定

git config --local core.hooksPath GitHooks

5. 手動実行用スクリプトの作成(オプション)

プロジェクトルートにformat.shファイルを作成し、以下の内容をコピペしてください:

#!/bin/bash

# SwiftFormat実行スクリプト
# 使用方法: ./format.sh [ファイル名]

set -e

# プロジェクトルートディレクトリに移動
cd "$(dirname "$0")"

# SwiftFormatの実行
if [ $# -eq 0 ]; then
    # 全ファイルをフォーマット
    echo "全Swiftファイルをフォーマットしています..."
    swiftformat .
else
    # 指定されたファイルをフォーマット
    echo "ファイル $1 をフォーマットしています..."
    swiftformat "$1"
fi

echo "フォーマット完了!"

実行権限を付与:

chmod +x format.sh

動作確認

1. 基本的な動作確認

# SwiftFormatが正常に動作するかテスト
swiftformat --version

# 設定ファイルが正しく読み込まれるかテスト
swiftformat SwiftfomatSample/ContentView.swift --dryrun

2. GitHooksの動作確認

テスト用ブランチの作成

# 新しいブランチを作成
git checkout -b test-swiftformat

フォーマットが崩れたコードの作成

意図的にフォーマットを崩したコードを作成します。
うまく設定ができていたらコミットでステージに上げた時にErrorFormatFnction.count == 0.isEmptyに置き換わるはずです。
以下の手順で、手動で実行することもできます。

スクリーンショット 2025-08-23 21.55.06.png

ContentView.swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .padding()
    }

    private func ErrorFormatFnction() {
        if [].count == 0 {}
    }
}

#Preview {
    ContentView()
}

トラブルシューティング

よくある問題と解決方法

1. SwiftFormatコマンドが見つからない

# エラーメッセージ
⛔️ swiftformatコマンドが見つかりません。

# 解決方法
brew install swiftformat

2. 設定ファイルの構文エラー

# エラーメッセージ
error: Unknown option --spacearoundoperators

# 解決方法
最新のSwiftFormatの正しいオプション名を使用
--no-space-operators  # 正しいオプション名

3. GitHooksが動作しない

# 確認事項
git config --local core.hooksPath  # GitHooksが表示されるか
ls -la GitHooks/pre-commit         # ファイルが存在し、実行権限があるか

4. mainブランチでフックがスキップされる

これは正常な動作です。mainブランチでの意図しない変更を防ぐための仕組みです。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?