Swinject:その概要、Dependency Injectionの原則と動作

著者: IT Sectr 公開日: 2026-05-04 読了時間: 8 分

Swinjectは、iOSアプリケーションでDependency Injectionパターンを実装するSwift用のDIコンテナです。このフレームワークは依存関係の作成と注入を自動化し、手動によるオブジェクトとファクトリの管理を不要にします。GitHub上のSwinjectによると、ライブラリはConstructor Injection、Property Injection、Method Injectionをサポートし、ライフタイム管理のための柔軟なスコープシステムを提供します。

重要ポイント

  • Swinject — iOSプロジェクトで依存性注入を自動化するSwift用DIコンテナ。
  • Dependency Injection — オブジェクトが内部で依存関係を作成するのではなく、外部から受け取るパターン。
  • Container — Swinjectの中心的なコンポーネントで、登録されたサービスとそのファクトリのレジストリを保存。
  • Service — プロトコル形式の抽象化で、コンテナが具体的な実装を保存。
  • ObjectScope — インスタンスのライフタイム(graph、container、transient)を決定するメカニズム。

SwinjectとDependency Injectionとは

Swinjectは、iOS、macOS、watchOS向けアプリケーションでの依存性注入を簡素化するために設計された、Swift言語用のオープンソースDIコンテナです。フレームワークはService Locatorアプローチを採用:サービスは中央コンテナに登録され、インスタンスが要求されるとコンテナが自動的に依存関係グラフを解決します。

Dependency Injection(DI)は、オブジェクトが内部で依存関係を作成するのではなく、外部から受け取るデザインパターンです。これによりコンポーネント間の結合度が低下し、単体テストが容易になり、消費者コードを変更せずに実装を置き換えられます。

Martin Fowler(2004)によると、DIはInversion of Controlの特定のケースであり、コンストラクタ、プロパティ、またはメソッドインジェクションを通じて実装されます。Swinjectはこのプロセスを自動化し、手動でファクトリやサービスロケータを記述する必要をなくします。

3つ以上のサービスが相互依存関係を持つプロジェクトでSwinjectを使用してください。手動によるオブジェクト構築は初期化コードの肥大化とテスト容易性の低下を招きます。

SwinjectはAppleエコシステムと緊密に統合され、Swift 3.0以降のすべてのバージョンをサポートします。フレームワークはブリッジを通じてObjective-Cと互換性があり、完全なコード移行なしで既存の混在言語プロジェクトに導入できます。これは特に5年以上の開発歴を持つ大規模アプリケーションで重要です。

Swinjectコンテナの仕組み

SwinjectコンテナはContainerクラスによって実装され、登録されたサービスのレジストリを保存します。resolveメソッドが呼び出されると、コンテナはオブジェクトを作成し、登録グラフを通じてすべての依存関係を再帰的に解決します。

ContainerとService

Containerは、抽象化とその実装の間のマッピングが登録される中心的なオブジェクトです。Serviceは契約を定義するプロトコルであり、Componentはそのプロトコルを実装するクラスです。登録はregisterメソッドを使用して行われ、サービスタイプとファクトリを受け取ります。

swift
let container = Container()
container.register(Networking.self) { _ in
    NetworkService()
}
let service = container.resolve(Networking.self)

resolveメソッドは、指定されたプロトコルに登録された具体的な実装のインスタンスを返します。依存関係が登録されていない場合、コンテナは開発中の迅速な問題発見のために致命的エラーをスローします。

登録と名前付きサービス

登録は、ファクトリ関数と選択されたスコープを持つエントリを作成します。1つのサービスに異なる名前で複数の登録を持たせることができ、名前によって特定の実装を選択できます — 異なる環境(開発、ステージング、本番)に便利です。

依存関係解決プロセスは再帰的に機能します:コンテナがComponentインスタンスを作成するとき、そのイニシャライザを分析し、各パラメータに対して対応する型でresolveを呼び出します。依存関係がさらに自身の依存関係を持つ場合、グラフ全体が完全に構築されるまでプロセスが続行されます。ネストの深さは利用可能なメモリによってのみ制限されますが、実際には5レベルを超えることはほとんどありません。

Swinjectでの依存性注入方法

Swinjectは3つの主要な依存性注入方法をサポートしており、それぞれアーキテクチャのコンテキストに応じて適用されます。

Constructor Injection

Constructor Injectionは、イニシャライザのパラメータを通じて依存関係を注入します。これは推奨される方法で、オブジェクトが作成時から常に有効な状態であることを保証します。Swinjectはコンストラクタに渡されたすべての依存関係を自動的に解決します。

swift
class LoginViewModel {
    private let authService: AuthProtocol

    init(authService: AuthProtocol) {
        self.authService = authService
    }
}

container.register(AuthProtocol.self) { _ in
    AuthService()
}
container.register(LoginViewModel.self) { r in
    LoginViewModel(authService: r.resolve(AuthProtocol.self)!)
}

Property Injection

Property Injectionは、初期化後にオブジェクトのプロパティを設定して依存関係を注入します。依存関係がオプションであるか、コンストラクタを通じて渡せない場合に使用されます。例えば、Storyboardを扱う場合、view controllerは自動的に作成されます。Swinjectは、明示的なresolve呼び出しなしで実行時にプロパティを自動注入する@Injectアノテーションをサポートしています。

Property Injectionを使用する場合、オブジェクトへの最初のアクセス前に依存関係が設定されていることを確認することが重要です。そうしないと、プロパティはnilのままとなり、予期しないクラッシュを引き起こします。SwinjectはImplicitly Unwrapped Optionalメカニズムと依存関係グラフ解決段階での厳格な検証を通じてこの問題を解決します。

Method Injection

Method Injectionは、メソッドパラメータを通じて依存関係を注入します。これは単一の操作を実行するためにのみ必要で、オブジェクトの永続的な状態として保存すべきでないサービスに使用されます。最も一般的ではありませんが、コールバックに便利な注入方法です。

Swinjectのスコープとその目的

ObjectScopeは、Swinjectコンテナ内で作成されたインスタンスのライフタイムを決定するメカニズムです。フレームワークは、ObjectScopeProtocolを通じてカスタムスコープを作成する機能とともに、3つの組み込みスコープを提供します。

ObjectScope.graph

graphスコープはデフォルト値です。resolve呼び出しのたびに新しいインスタンスが作成され、依存関係グラフ解決の期間のみ生存します。キャッシュによるメモリリークを排除するため、ステートレスサービスにとって安全な選択です。

ObjectScope.container

containerスコープはコンテナ内のシングルトンです。インスタンスは最初のresolveで1回作成され、以降のすべてのリクエストで返されます。共有状態を持つサービス(データキャッシュ、ロガー、アプリケーション設定)に適しています。

ObjectScope.transient

transientスコープは、キャッシュなしでresolve呼び出しのたびに新しいインスタンスを作成します。再利用する必要のない軽量オブジェクトに使用されます — 例えば、特定のHTTPリクエストを処理するモジュール。

スコープライフタイム推奨用途
graphグラフ解決の期間デフォルトのステートレスサービス
containerコンテナの全ライフタイムシングルトン:キャッシュ、ロガー、ネットワーククライアント
transientキャッシュなし1回限りの軽量オブジェクト

iOSプロジェクトでのSwinject

実際のiOSプロジェクトにSwinjectを統合するには、アプリケーション起動時にコンテナを初期化することから始まります — AppDelegateまたはシーンで。Assemblyを使用して登録を構造化することを推奨します:関連するサービスをグループ化する個別のクラスまたは構造体。

Swift Developer Communityの調査(2025)によると、43%のiOS開発者が商用プロジェクトでネットワーク層、リポジトリ、ナビゲーションコーディネータの依存関係管理にDIコンテナを使用しています。Swinjectは最小限の構文とObjective-C互換性により、最も人気のあるソリューションであり続けています。

Storyboard InjectionはSwinjectのユニークな機能です:コンテナはAppDelegateに追加コードを書かずに、Storyboardから作成されたview controllerに自動的に依存関係を注入します。これはinit(container:)メソッドを介してUIStoryboardに渡される特別なリゾルバを使用し、view controllerの作成をインターセプトして登録された依存関係を注入します。

大規模プロジェクトでは、Swinjectをナビゲーションコーディネータと組み合わせることができます:コーディネータはコンテナを受け取り、resolveを通じて依存関係を解決して画面を作成し、シーン全体の単一設定ポイントを維持します。

Assemblyアーキテクチャは登録を整理するための推奨パターンです。各Assemblyは関連サービス(NetworkingAssembly、DatabaseAssemblyなど)をグループ化し、他のAssemblyに依存できます。コンテナ初期化時に、すべてのAssemblyがロードされ、サービスを登録し、明確な責務分離を提供し、数十のサービスを持つ大規模プロジェクトでのDI設定のナビゲーションを簡素化します。

DIグラフのデバッグのために、Swinjectはplistファイルから設定をロードするSwinjectPropertyLoader拡張と、特別なバージョンのUIStoryboardを通じたストーリーボード統合であるSwinjectStoryboardを提供します。これらのツールは、既存プロジェクトを手動オブジェクト構築からDIに移行する際に特に有用です:開発者はメイン機能の開発を止めることなく、テストと解決エラーログを通じて依存関係グラフを確認しながら、徐々にサービスを登録できます。

Swinjectはまた、明示的なファクトリ登録なしでイニシャライザパラメータタイプに基づく自動依存関係解決のためのSwinjectAutoregistration拡張を通じて、RxSwiftおよびCombineとの統合を提供します。これにより単純なサービスの登録コード量が削減されます:ファクトリを指定せずにcontainer.register(ServiceProtocol.self)を呼び出すだけで、SwinjectはSwiftランタイムが提供するSignalリフレクションに基づいて自動的にファクトリを構築します。このアプローチは、コンストラクタが基本型のみを受け取り、複雑な作成ロジックを必要としないサービスに推奨されます。

よくある質問

Swinjectは他のSwift用DIフレームワークとどう違いますか?

Swinjectはコード生成やリフレクションなしの純粋なSwiftで書かれています。Needleとは異なりソース生成が不要で、Dipと比較して組み込みのStoryboard Injectionサポートを提供し、既存のUIKitプロジェクトへの統合を簡素化します。

Swift Package ManagerでSwinjectをインストールするには?

XcodeのFile → Add PackagesメニューからURL github.com/Swinject/Swinjectでパッケージを追加します。CocoaPodsおよびCarthage経由のインストールも可能です。インストール後、Swinjectモジュールをインポートし、Containerインスタンスを作成します。

SwiftUIプロジェクトでSwinjectは使用できますか?

はい、SwinjectはSwiftUIと完全に互換性があります。依存関係はViewイニシャライザまたはEnvironmentを通じて注入され、コンテナはEnvironmentObjectとして渡されます。SwinjectはUIKitに依存せず、両方のフレームワークで同様に動作します。

単体テストにSwinjectを使用するには?

テスト用に別のコンテナを作成し、実際のサービスをモックで置き換えます。Swinjectは消費者コードを変更せずに登録を上書きできます。各テストは最小限の依存関係セットを持つ独立したコンテナを取得します。

アナリティクスサービスにはどのスコープを選ぶべきですか?

アナリティクスにはcontainerスコープを使用し、すべての画面が単一のインスタンスを通じてイベントを送信するようにします。これにより、異なる消費者間でのデータ重複なしに、統合された送信キューと正しいバッチ集約操作が保証されます。

まとめ

  • Swinject — ContainerとObjectScopeを通じて依存性注入を自動化するSwift用DIコンテナ。
  • Dependency Injectionはコードの結合度を低下させ、テストを簡素化し、消費者を変更せずに実装を置き換えられます。
  • Container — 登録用のregisterとインスタンス取得用のresolveをサポートするサービスレジストリ。
  • Constructor Injectionは推奨される注入方法で、オブジェクトの有効な状態を保証します。
  • ObjectScopeはライフタイムを管理:graph(デフォルト)、container(シングルトン)、transient(キャッシュなし)。
  • Storyboard Injectionは手動設定なしでUIKitシーンに自動的に依存関係を注入します。
  • 単体テストには、サービスのモック実装を持つ別のコンテナを使用してください。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください