まくら
Navigation Controller
を使ったアプリを作っている時に、稀によくある問題に対するアプローチです。
例えばこんな場合
- とある画面で時間のかかる処理中に読み込み中のインジケータを出したい
- インジケータが出ている間はナビゲーションバーの操作(戻るボタンとか)を無効にしたい
インジケータを出すのはいいとして、操作を無効にする方法はいくつか思いつきますが、今回は前面に目隠しを出して操作できないようにしてみましょう。
ほんだい
まずはソースをどうぞ。
インジケータを表示する部分です。
// インジケータを表示する
private func showIndicator() {
// 背景になるView
let backView = UIView()
backView.backgroundColor = UIColor.init(white: 0.0, alpha: 0.5)
backView.tag = 12345 // 消す時用にタグを付けておく
// インジケータ
let indicator = UIActivityIndicatorView()
indicator.activityIndicatorViewStyle = .whiteLarge
indicator.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
// NavigationControllerのViewを使う
guard let naviView = self.navigationController?.view else {
return
}
// 背景にインジケータを貼り付け
backView.addSubview(indicator)
// 背景をNavigationControllerのViewに貼り付け
naviView.addSubview(backView)
// サイズ合わせはAutoLayoutで
backView.translatesAutoresizingMaskIntoConstraints = false
backView.topAnchor.constraint(equalTo: naviView.topAnchor).isActive = true
backView.bottomAnchor.constraint(equalTo: naviView.bottomAnchor).isActive = true
backView.leftAnchor.constraint(equalTo: naviView.leftAnchor).isActive = true
backView.rightAnchor.constraint(equalTo: naviView.rightAnchor).isActive = true
// インジケータもAutoLayout
indicator.translatesAutoresizingMaskIntoConstraints = false
indicator.centerXAnchor.constraint(equalTo: backView.centerXAnchor).isActive = true
indicator.centerYAnchor.constraint(equalTo: backView.centerYAnchor).isActive = true
indicator.widthAnchor.constraint(equalToConstant: 100).isActive = true
indicator.heightAnchor.constraint(equalToConstant: 100).isActive = true
// インジケータ起動
indicator.startAnimating()
}
これを適当に実装するとこんな感じになります。
ポイントはNavigationBar
がグレーのView
に覆われていてBarButtonItem
が押せない状態になっているところです。
ここですね。
// NavigationControllerのViewを使う
guard let naviView = self.navigationController?.view else {
return
}
// 背景をNavigationControllerのViewに貼り付け
naviView.addSubview(backView)
要は、NavigationController.View
にもaddSubView
できますよって事ですね。
NavigationController
の上にView
を貼り付けるので、当然その下のボタン等は押せなくなるわけです。
ちなみに注意点としては、当然ですが、NavigationController.View
が存在しないと使えません。
prepare for segue
の遷移時などNavigationController
が追いづらい時には正直使いづらいです。
現場からは以上です。