はじめに
この記事の目的は、コードから、Container View Controllerを作れるようになることです。
子ViewControllerが一つである単純な例で説明を行います。
参考文献の書籍の内容です。
ちなみに、storyboardからも、ContainerView(確かこんな名前のWidget)を使えばContainer View Controllerを作成可能です。
Container View Controllerとは
ViewControllerの中に他のViewControllerを表示するとき、
親になっているViewControllerをそう呼びます。
UINavigationControllerやUITabBarControllerなどは、Container View Controllerにあたります。
androidだとFragmentを持つActivityのようなものです。
方法
UIViewControllerでは、子ViewControllerを格納するためのchildren
プロパティが用意されていますが、プロパティを直接扱うことは非推奨です。
childrenプロパティに子ViewControllerを格納するには決まったお作法があり、技術書によれば、作法を破ると手痛い仕打ち(バグ)を受けるとのこと。
つまり、Container View Controllerの作成は、このお作法に則って行う必要があります。
お作法
add 子ViewController
- 親になるView Controller(以降親VCと呼称)の
addChild(_:)
をコール。引数は子ViewController(以降子VCと呼称)。 - 親VCのview.addSubview(_:)によって、子VCのviewを加える。
- 子VCの
didMove(toParent:)
を引数親VCでコール。
※1. 子VCが親VCのchildren
に格納されるだけでなく、自動で子VCのwillMove(toParant:)
が引数親VCで呼ばれる。
remove 子ViewController
本記事の例では扱いませんが、一応removeも。
- 子VCの
willMove(toParent:)
を引数nilでコール。 - 子VCのviewを親VCのviewから除外する。
- 子VCの
removeFromParent()
をコール。
※3. 子VCがchildren
から除外されるだけでなく、自動で子VCのdidMove(toParant:)
が引数nilで呼ばれる。
具体例
子としてPageViewControllerを持つcontaner view controllerを作成します。
初期画面のボタンを押すと、contaner view controllerに遷移するようにしました。
/// 初期表示画面。この画面の上にcontainer view controllerを表示してみる。
class InitialViewController: UIViewController {
~
// buttonのタッチイベントアクション。container view controllerを作成し、表示する処理を書きます。
@IBAction func onButton(_ sender: UIButton) {
// 親vc(contaner view controller)と子vcの作成
let pvc = UIViewController()
let cvc = MyPageViewController()// 前もって作成済みのもの。ペラペラめくれます。
// 色を分けて見やすく
pvc.view.backgroundColor = .white
cvc.view.backgroundColor = .blue
// addのお作法
// 1
pvc.addChild(cvc)
// 2
cvc.view.translatesAutoresizingMaskIntoConstraints = false
pvc.view.addSubview(cvc.view)
NSLayoutConstraint.activate([// 親vcの下半分に子vcを表示してみる
cvc.view.leadingAnchor.constraint(equalTo: pvc.view.leadingAnchor),
cvc.view.trailingAnchor.constraint(equalTo: pvc.view.trailingAnchor),
cvc.view.bottomAnchor.constraint(equalTo: pvc.view.bottomAnchor),
cvc.view.heightAnchor.constraint(equalTo: pvc.view.heightAnchor, multiplier: 0.5)
])
// 3
cvc.didMove(toParent: pvc)
present(pvc, animated: true)
}
~
}
参考文献
より詳しくはこちら。
再利用可能なContainer View Controllerはこちらの記事が良さげでした。