この記事は公開されてから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を使用する処理を追加します。