UIViewControllerをオーバレイ表示させる
Dec 7, 2017 · iosswift3
概要
UIViewControllerをUIAlertControllerみたいに表示させるのをStoryboardで実現する方法
例えば、くるくるとインジケータを回したい画面をオーバレイで表示させたい時とかに使える
メリット
古い時代の実装だと、画面はnibで作るかコードで実装、表示させたい時にaddSubviewしていた分だが、
こちらの方がいろいろとメリットが大きい
ざっと思いつくだけでも、
ViewControllerが持てるのでライフサイクル周りのイベントが取れる- 他の
ViewController、特にUIAlertControllerと同じ様に扱えるので便利で判りやすい AutoLayoutが使える(自分で実装しなくて良い)- 書くコードの量が減る
- 標準の手法である
といったあたり
(よくStoryboardを覚えるのが大変だから、コードで実装した方が良い派がいるけど、個人的にはどう考えても
UIViewControllerが中でやっているライフサイクルの管理やAutoLayout等を全部、
しかも各OSのバージョン毎に覚えて実装してテストする方が大変だと思う)
作り方
表示したい画面を作る
通常の画面と同じ要領で表示したいViewControllerを作る
この時、本来のアプリの画面で使うStoryboardとは別のStoryboardで作成しておくと、
nibファイルみたいに他のプロジェクトで使い回すことも容易になるのでオススメ
(これに限らず、Storyboardはこまめに分割しておくとコンフリクトも起こりにくくなるので良い)
作成できたら、以下の設定を行う
ViewControllerのViewのBackgroundを 半透明 で設定する- 透過させたくないViewは
Opaqueにチェックを入れる ViewControllerのTransition StyleをCross Dissolveに設定する(※)
(画面を表示する際のアニメーション。通常だと違和感があるのでこれに変える)ViewControllerのPresentationをOver Full Screenに設定する(※)
※:もし、後述のセグエを使って表示しか使わない場合は設定不要(セグエでの設定が優先されるため)
例
インジケータを表示させるIndicatorViewControllerを作りたい場合、、、
画面イメージとしては、ボタンのないUIAlertControllerの様に画面中央に白いViewがあり、その上にUIActivityが載っている状態。また、画面中央の白いView以外の部分は黒の半透明で、元のViewControllerが表示されている
この場合は白いViewのOpaqueにチェックを入れる
表示させる
大きく分けると、
- セグエを使って表示
presentを使って表示
の2つになる
セグエを使う
データの受け渡しが面倒なのと、そもそもモーダル表示を他の画面遷移と同列に扱うのか?といったあたりがあるので、あまり使わない方法
基本的には通常の画面遷移と同じ。
(専用のStoryboardに作った場合は、Storyboard Referenceを使う)
セグエの設定ポイントは、
KindをPresent Modallyに設定するPresentationをOver Full Screenに設定するTransition StyleをCross Dissolveに設定する
(画面を表示する際のアニメーション。通常だと違和感があるのでこれに変える)
である。この設定にすると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しても良い
開発環境
- Xcode 9.1
- iOS 11.1
