[iOS] StoryboardからのViewController生成時にDIを行う(外部ライブラリ不使用)

本記事ではiOS 13で追加されたメソッドを使用して、StoryboardからのViewController生成時にDIする実装を紹介します
2021.11.08

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは。平屋です。

StoryboardからViewControllerを生成するタイミングでDI(Dependency Injection、依存性の注入)を行う実装を試してみましたので紹介します。

本記事で紹介する実装では、iOS 13で追加されたメソッドを使用しています。

検証環境

  • macOS Big Sur 11.4
  • Xcode Version 12.5.1

(1) 生成される側のViewControllerの実装例

class DetailViewController: UIViewController {
    // (1-4)
    @IBOutlet weak var label: UILabel!

    // (1-1)
    let value: String

    override func viewDidLoad() {
        super.viewDidLoad()

        // (1-5)
        label.text = value
    }

    // (1-2)
    init?(coder: NSCoder, value: String) {
        self.value = value
        super.init(coder: coder)
    }

    // (1-3)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

本サンプルでは、Stringを渡してViewControllerを生成してみます。

(1-1) プロパティを定義する

ViewController生成時に渡される値を保持するためのプロパティを定義します。値はイニシャライザの引数として渡されるので、このようにlet、非オプショナルでプロパティを定義できます。

(1-2) イニシャライザを定義する

イニシャライザの引数の1つはNSCoder型にし、呼び出し側から渡されたNSCoderを使ってsuper.init(coder:)を呼ぶようにします。

その他の引数は、対象画面で必要なものを定義します。本サンプルでは、2つ目の引数としてString型の引数を定義し、渡された値を(1-1)のプロパティに設定しています。

(1-3) init?(coder:)を追加する

(1-2) のイニシャライザを追加すると、init?(coder:)の実装が必要になるので、追加します。

(1-4)、(1-5) プロパティを使用する

後は、値を使用する処理を追加します。本サンプルでは、UILabelに値を設定しています。

(2) ViewController生成の実装例

class ViewController: UIViewController {
    @IBAction func detailButtonDidTap(_ sender: Any) {
        let storyBoard = UIStoryboard(name: "Main", bundle: nil)

        // (2-1)
        let controller = storyBoard.instantiateViewController(identifier: "DetailViewController") { coder in
            return DetailViewController(coder: coder, value: "Test")
        }

        // (2-2)
        navigationController?.pushViewController(controller, animated: true)
    }
}

(2-1) ViewControllerを生成する

本サンプルでは、iOS 13で追加されたinstantiateViewController(identifier:creator:)を使用して、ViewControllerを生成しています。creator引数で指定するクロージャ内では、(1-2)のイニシャライザを使用しています。

Storyboard上のInitialViewControllerを生成する場合は以下のメソッドを使用できます。

(2-2) ViewControllerを使用する

(1)で作成したViewControllerを使用する処理を追加します。

参考資料