ソフトウェア設計

イニシャライザ注入・プロパティ注入・メソッド注入、どれを使うべき?(Swift DIまとめ)

SwiftでiOSアプリを作っていると、必ず直面する悩みがあります。

読了 5 分
イニシャライザ注入・プロパティ注入・メソッド注入、どれを使うべき?(Swift DIまとめ)のカバー画像

SwiftでiOSアプリを作っていると、必ず直面する悩みがあります。

「依存性注入って、結局どの方法が正しいの?」

結論からお話しします。

特別な理由がなければ、イニシャライザ(init)注入を使うのが最善に近い選択です。

なぜそうなのか、そして残り2つの方法をいつ使うのかを、実体験をもとに解説します。


3つの注入方法、まず要点を整理

混乱する前に、まず基本を押さえましょう。Swiftで依存性を渡す方法は、大きく3つあります。

  1. イニシャライザ(init)注入initパラメータで依存性を受け取る
  2. プロパティ注入var後からプロパティに代入する
  3. メソッド注入 — 別のメソッドで注入する

まず、最も推奨されるイニシャライザ注入のコードを見てみます。

final class OrderService {
    private let repo: MemberRepository // let 不変性を保証

    init(repo: MemberRepository) { // イニシャライザ(init) 注入
        self.repo = repo
    }
}

追加ライブラリなしで純粋なSwiftの構文だけで書けるため、コードがすっきりします。

一方、プロパティ注入はこのように短く書けます。

final class OrderService {
    var repo: MemberRepository! // 1行なので便利そうに見えますが…
}

一見するとプロパティ注入のほうが簡単そうです。しかし、その便利さが後で問題になります。


なぜプロパティ注入は避けるべきなのか?

まず、私が実際に経験したことからお話しします。

プロパティ注入はテストで本当に扱いづらい方法です。オブジェクト作成後に注入を忘れると、オプショナルの強制アンラップでクラッシュします。型を見るだけでは、何を渡せば完成するのかも分かりません。

イニシャライザ注入なら、OrderService(repo: mockRepo)のように純粋なSwiftコードでモックオブジェクトをすぐ渡せます。

2つ目の問題は、letキーワードを使えないことです。

イニシャライザ注入ならプロパティをletとして宣言できるため、注入後に変わらない不変オブジェクトになります。

一方、プロパティ注入はvarなので、値をいつでも変更でき、ミスの余地が生まれます。

3つ目は循環参照の問題です。

AがBを、BがAを相互に参照している場合、プロパティ注入ではアプリが実行されるまで気づけません。該当画面に遷移して初めてクラッシュします。

イニシャライザ注入ならオブジェクト作成時に問題が明らかになり、設計が複雑ならコンパイルすらできないため、より早く問題を見つけられます。

循環参照は、クラッシュするタイミングからして違います
循環参照は、クラッシュするタイミングからして違います
フィールド注入だけを使っていた頃は、テストを書くたびに苦労しました
フィールド注入だけを使っていた頃は、テストを書くたびに苦労しました

比較表で一目で確認

文章だけでは分かりにくいので、表にまとめました。(2026年時点のSwiftコミュニティ推奨方針)

項目 イニシャライザ(init)注入 プロパティ注入 メソッド注入
不変性(let) 可能 ⭕ 不可 ❌ 不可 ❌
テストのしやすさ 高い 低い 普通
循環参照の検出 生成時に即時 発見が遅い 発見が遅い
必須/任意の依存性 必須に適する 区別が曖昧 任意に適する
コードの簡潔さ 普通 非常に簡潔 普通

表を見るだけでも傾向が分かりますよね。

イニシャライザ注入は、ほとんどの項目で優れています。そのため、SwinjectやFactoryなどのDIライブラリのドキュメントでも、基本として推奨されています。


では、残り2つの方法はいつ使うのか?

必ずイニシャライザ注入だけを使うという意味ではありません。それぞれ適した場面があります。

メソッド注入は任意の依存性に向いています。

注入対象がなくてもよい場合、つまりあれば使い、なくても問題ない依存性には、configure(with:)のようなメソッドで柔軟に渡せます。

プロパティ注入にも、ストーリーボードで作成したビューコントローラのように、初期化のタイミングを直接制御できない場所では使い道があります。

通常のアプリケーションコードでは、できるだけ避けるのがよいでしょう。

まとめると、次のとおりです。

  • 必須の依存性 → イニシャライザ注入
  • 任意の依存性 → メソッド注入
  • 通常のコードでのプロパティ注入 → 避ける

よくある質問

Q. FactoryのようなDIライブラリを使うと、イニシャライザ注入はもっと簡単になりますか?

はい。SwinjectやFactoryに依存性の生成方法を登録しておけば、コンテナがイニシャライザに渡すオブジェクトを代わりに作ってくれます。コードを短くしながら、let不変性などの利点も維持できます。

Q. イニシャライザのパラメータが多くなりすぎたら?

それは注入方法の問題ではなく、そのクラスが多くの仕事を抱えているサインです。まず責務を分けてクラスを分離することを検討してください。

Q. 小規模なプロジェクトでもDIライブラリは必要ですか?

いいえ。画面が数個程度なら、initとして直接渡す純粋なイニシャライザ注入だけで十分です。

迷ったときは、この順番で選ぶと簡単です
迷ったときは、この順番で選ぶと簡単です

最初はプロパティ注入の手軽さに惹かれがちですが、テストを書き、協業するようになると、なぜイニシャライザ注入の利点が強調されるのかを実感します。

迷ったら、まずイニシャライザ注入から始めてみてください。コードが大きくなるほど、その選択に感謝するはずです。