UIViewControllerをオーバレイ表示させる

概要

UIViewControllerUIAlertControllerみたいに表示させるのをStoryboardで実現する方法

例えば、くるくるとインジケータを回したい画面をオーバレイで表示させたい時とかに使える

メリット

古い時代の実装だと、画面はnibで作るかコードで実装、表示させたい時にaddSubviewしていた分だが、 こちらの方がいろいろとメリットが大きい

ざっと思いつくだけでも、

といったあたり

(よくStoryboardを覚えるのが大変だから、コードで実装した方が良い派がいるけど、個人的にはどう考えても UIViewControllerが中でやっているライフサイクルの管理やAutoLayout等を全部、 しかも各OSのバージョン毎に覚えて実装してテストする方が大変だと思う)

作り方

表示したい画面を作る

通常の画面と同じ要領で表示したいViewControllerを作る

この時、本来のアプリの画面で使うStoryboardとは別のStoryboardで作成しておくと、 nibファイルみたいに他のプロジェクトで使い回すことも容易になるのでオススメ
(これに限らず、Storyboardはこまめに分割しておくとコンフリクトも起こりにくくなるので良い)

作成できたら、以下の設定を行う

※:もし、後述のセグエを使って表示しか使わない場合は設定不要(セグエでの設定が優先されるため)

インジケータを表示させるIndicatorViewControllerを作りたい場合、、、

画面イメージとしては、ボタンのないUIAlertControllerの様に画面中央に白いViewがあり、その上にUIActivityが載っている状態。また、画面中央の白いView以外の部分は黒の半透明で、元のViewControllerが表示されている

この場合は白いViewのOpaqueにチェックを入れる

表示させる

大きく分けると、

の2つになる

セグエを使う

データの受け渡しが面倒なのと、そもそもモーダル表示を他の画面遷移と同列に扱うのか?といったあたりがあるので、あまり使わない方法

基本的には通常の画面遷移と同じ。 (専用のStoryboardに作った場合は、Storyboard Referenceを使う)

セグエの設定ポイントは、

である。この設定にするとUIAlertControllerに似た表示のされ方となる

コードから呼び出す

例のインジケータを表示させるIndicatorViewControllerの場合だと、生成するコードは、

static func instantiate() -> IndicatorViewController {
    let storyboard = UIStoryboard(name: 作成したストーリーボード名, bundle: nil)
    return storyboard.instantiateViewController(withIdentifier: ストーリーボード上のID) as! IndicatorViewController
}

となり、IndicatorViewControllerのクラスメソッドとしておく

使う時は、

let indicator = IndicatorViewController.instantiate()
present(indicator, animated: true)

とすれば表示される

表示元のViewControllerから閉じたい場合は、

presentedViewController?.dismiss(animated: true)

の1行で閉じても良いし、先ほどの生成したIndicatorViewControllerを保持してdismissしても良い

開発環境