遷移中にNavigationBarの設定をアニメーションさせて綺麗に見せる
背景
PushやModal遷移の時に呼び出し元ViewControllerと呼び出し先ViewControllerでNavigationBarやボタンの色が違う時に、その遷移の進捗に応じて設定の色などをアニメーションで変えて綺麗に見せたいかった
方法
UIViewControllerTransitionCoordinatorのメソッドである
func animate(alongsideTransition animation: ((UIViewControllerTransitionCoordinatorContext) -> Void)?, completion: ((UIViewControllerTransitionCoordinatorContext) -> Void)? = nil) -> Bool
を使えば良い。
UIViewControllerTransitionCoordinatorはUIViewControllerのプロパティとして定義されている。
例えばNavigationBarの設定が違うMainViewControllerとDetailViewControllerあるとする


設定は呼び出し元のMainViewController.swifが
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.barTintColor = .blue
self.navigationController?.navigationBar.tintColor = .white
}
遷移先のDetailViewController.swif
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
transitionCoordinator?.animate(alongsideTransition: { _ in
self.navigationController?.navigationBar.tintColor = .red
self.navigationController?.navigationBar.barTintColor = .yellow
}, completion: nil)
}
といったようにやると、Pushなどの遷移中に遷移の比率に応じてアニメーションで色が変わっていくの良い。 シュミレーターの[Debug]-[Slow Animations]をONにして確かめると一目瞭然。
エッジスワイプバックのキャンセル対応
エッジスワイプで前の画面に戻ろうとしてキャンセルする操作をすると、ライフサイクル的に呼び出し元の画面のviewWillAppearが呼ばれ、現在表示されている遷移先画面はviewDidAppearが呼ばれるので、この実装だとエッジスワイプバックのキャンセルをすると、遷移元であるMainViewControllerの設定がDetailViewControllerに反映されてしまう。


なのでDetailViewControllerでtransitionCoordinator?.animateメソッドのcompletionブロックで、この画面の完成形となる色設定などを書いてあげておくと、違う画面の設定になってしまうということを防げる。
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
transitionCoordinator?.animate(alongsideTransition: { _ in
self.navigationController?.navigationBar.tintColor = .red
self.navigationController?.navigationBar.barTintColor = .yellow
}, completion: { _ in
self.navigationController?.navigationBar.tintColor = .red
self.navigationController?.navigationBar.barTintColor = .yellow
})
}