Container View を使って delegate

ViewController の中に UIView と UILabel がセットになった View を置きたくなり、それって、結局、ViewController の中に ViewController を配置するということか?と思い、はて、いったいどうやるんだ? Storyboard に配置した ViewController の中に ViewController は置けなくて、普通にやると ViewController は独立した画面のようになってしまうわけだ。

ちょっと調べてみたら、Container View という仕組みがあるとのことで試してみた。

まず、Storyboard の ViewController の中に、Library から Container View を選んで配置する。すると、元からある ViewController には、UIView が配置され、同時に segue 接続された ViewController が表示される。新しく配置された ViewController はいつもとは少し様子が違い、ウインドウのサイズが小さい。元の ViewController の一部分なので、小さく表示されている方が分かりやすく、これイイね。

Container View を配置した画面では UIVew で、Outlet として登録可能。また、segue 接続された先では UIViewController 扱いなので、専用の m ファイルを記述できる。build して画面表示すると、Container View を配置した ViewController が表示されると自動的に segue 接続された ViewController も load され表示される。要は、UIView だったり、UIViewController だったりするわけなんだけど、少しハマったのが、container view を 初めは非表示にしておいて、ボタンを押したら表示、 longPress したら非表示のようなことをしようとするとうまくいかない。理由は表示・非表示の指定を UIView に対して行うべきか、あるいは segue 接続された UIViewController に対して指定すべきかが曖昧だったから。

解決方法は、segue 接続された ViewController に delegate 設定して、long press したら delegate を通じて container view を配置した ViewController で操作することでうまくいった。contaner view を配置した viewContoroller で delegate = self; という指定が、どうやうるのか悩ましかったんだけど、ViewDidLoad に続いて prepareForSegue が実行されるようで、そこで、destinationSegue を拾って self を指定してやることで delegate を受け取れるようになった。

 合理的な方法かは分からないけど、ま、ひとまずこれで進めよう。