popToRootViewControllerで画面を消すとviewWillDisappearでnavigationControllerがnilになる
現象が伝えにくいので、図に表すと以下のような感じで、 TabbarController内にNavigationControllerをもたせた状態で、いくつかViewControllerをPushViewControllerします。 そして、2つ以上PushViewControllerした状態で一番上のViewControllerのナビバーを透明にした場合にちょっと問題が発生します。
一番上のViewControllerでは以下のようにして、ナビバーを透明にして、消すときにナビバーを元に戻す用にしています。
class SampleViewController: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) navigationController?.navigationBar.shadowImage = UIImage() navigationController?.navigationBar.isTranslucent = true } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) navigationController?.navigationBar.setBackgroundImage(nil, for: .default) navigationController?.navigationBar.shadowImage = nil navigationController?.navigationBar.isTranslucent = false } }
普通に戻るボタンを押した場合はこれで正常に動作するのですが、 タブバーのボタンをタップしてrootviewcontrollerに戻った場合に、viewWillDisappearが呼ばれたときにはnavigationControllerがnilになっているため、ナビバーが透明なままになってしまうという問題が発生しました。。
対策
その1
やっつけ仕事感のある対応としてはnavigationControllerを自力で保持するというやりかたで、、
private weak var toKeepNavigationController: UINavigationController? override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) toKeepNavigationController = navigationController navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) navigationController?.navigationBar.shadowImage = UIImage() navigationController?.navigationBar.isTranslucent = true } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) toKeepNavigationController?.navigationBar.setBackgroundImage(nil, for: .default) toKeepNavigationController?.navigationBar.shadowImage = nil toKeepNavigationController?.navigationBar.isTranslucent = false }
その2
willMoveToParentViewControllerの時点ではnavigationControllerはnilになっていないようだったので、ViewControllerが消えるタイミング(parentがnilになったとき)にナビバーをもとにもどします
override func willMove(toParentViewController parent: UIViewController?) { super.willMove(toParentViewController: parent) if parent == nil { navigationController?.navigationBar.setBackgroundImage(nil, for: .default) navigationController?.navigationBar.shadowImage = nil navigationController?.navigationBar.isTranslucent = false } }
たぶん2のほうがいいと思います!
おかしいぞとかあればツッコミお願いします!