iOS13から特定のスタイルでモーダル遷移をすると画面を閉じた際、 遷移元のライフサイクルメソッドが発火されない仕様になったのを今更知知りました。
画面を閉じた際、遷移元のviewWillAppearで画面表示時に毎回ある処理をさせたかったのですが、モーダルを閉じた際の検知で代用することにしました。
閉じた際の検知はUIAdaptivePresentationControllerDelegateのpresentationControllerDidDismissメソッドを使って特定できるみたいです。
中身としては以下のように画面遷移する際にpresentationControllerのdelegateを自身にセットします。
// 遷移元コード全体
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
// ボタンを押したら遷移する処理
@IBAction func button(_ sender: Any) {
transitionToSecondVC()
}
private func transitionToSecondVC() {
guard let vc = UIStoryboard(name: "SecondVC", bundle: nil).instantiateViewController(withIdentifier: "SecondVC") as? SecondVC else {return}
vc.modalPresentationStyle = .overFullScreen
// delegateを自身に委任
vc.presentationController?.delegate = self
self.present(vc, animated: true)
}
}
extension ViewController: UIAdaptivePresentationControllerDelegate {
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
print("VC didDismiss")
}
}
ただこれだけ書けば遷移先でdismissしたら発火するわけでも無いみたいで、さらに遷移先でdismissする時に親のpresentationControllerDidDismissメソッドを呼び出す必要があるらしいみたいです。
// 遷移先コード全体
class SecondVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
// 閉じるボタンで画面を閉じる処理
@IBAction func closeButton(_ sender: Any) {
// dismiss前にpresentationControllerDidDismiss(_:)を呼び出す
if let presentationController = presentationController {
presentationController.delegate?.presentationControllerDidDismiss?(presentationController)
}
self.dismiss(animated: true)
}
}
こうすることで.overFullScreenで表示したSecondVCがdismissした時に、遷移元のViewControllerの print(“VC didDismiss”)が出力されるようになりました。
またモーダル画面先でナビゲーションコントローラーを使用する場合は下記のように実装します。
private func transitionToSecondVC() {
guard let vc = UIStoryboard(name: "SecondVC", bundle: nil).instantiateViewController(withIdentifier: "SecondVC") as? SecondVC else {return}
let nav = UINavigationController(rootViewController: vc)
nav.modalPresentationStyle = .overFullScreen
// navigationControllerのpresentationController delegateを自身に委任
nav.presentationController?.delegate = self
self.present(nav, animated: true)
}
そして遷移先で閉じるときはnavigationControllerのpresentationControllerを引数に入れてメソッドを呼び出します。
if let presentationController = self.navigationController?.presentationController {
presentationController.delegate?.presentationControllerDidDismiss?(presentationController)
}
とりあえずこうすれば画面を閉じた時の検知ができるので、発火されないViewWillAppearの代わりとして使用できそうです。
これが最適かは分からないですが、とりあえず現状これ以外のいい方法は分からなかったです。
終