【Swift5/Xcode】モーダルからdismissで戻ったときに処理をする方法

サトリク

この記事では、モーダル表示してから、dismissで戻るときに、処理を画面遷移元で処理する際に少し手間取ったので、記事にします。

動作環境

item Version
Swift 5.2.2
Xcode 11.4.1

バージョンの確認方法

やりたいこと

モーダル表示してから、閉じるを押したときに、処理を実行したい。

以下の動画のように、閉じるボタンを押したときに、遷移元の背景色を変更するなどの処理をしたい。

iOS12以前の対応

override func viewDidAppear(_ animated: Bool) {
    //やりたい処理
}

遷移元のViewControllerの中で上記のメソッド内に処理を書くと、モーダル表示の閉じるを押したときに、処理が行われます。

 

しかし、iOS13以降このように、するだけでは処理できなくなりました。

iOS12とiOS13のモーダル表示の違い

iOS12のモーダル表示は、単に下から上にアニメーションし画面遷移します。

しかし、iOS13のモーダル表示はiOS12と違い、中途半端なところで遷移が終わります。また、閉じるボタンを押さなくても、したにドラッグすることで、遷移元に戻ることができます。

iOS13以降の対応

対応は大きく分けて以下の2つあります。

  • フルスクリーンにする方法
  • presentationControllerDidDismissで実装する方法

フルスクリーンにする方法

iOS12とiOS13の違いは、先ほども言った通り、フルスクリーンになるかならないかの違いです。

iOS13でも、storyboardから「presentation」を「FullScreen」に変更するだけで、iOS12のような挙動にできます。

こうすることで、iOS13でもviewDidAppearメソッドでも呼ばれるようになり、処理を書き込むことができます。

サトリク

これが一番手っ取り早い対処法だと思います。

実際にフルスクリーンにする方法で実装してみる

STEP.1
FullScreenにする

①ボードのバーをクリック

(Attributes Inspector)を選択

③「presentation」を「FullScreen」に変更

STEP.2
処理を記述する

ViewController(遷移元)に以下の記述をする

override func viewDidAppear(_ animated: Bool) {
    //処理
}
完了

これで呼ばれると思います。

presentationControllerDidDismissで実装する方法

フルスクリーンにはしたくないなら、以下の対応をするといいでしょう。

遷移元の処理:モーダル表示する際に以下のような記述をする

以下のように、nextView.presentationController?.delegate = selfを追加する

let nextView = storyboard?.instantiateViewController(identifier: "Next") as! NextViewController
nextView.presentationController?.delegate = self
present(nextView, animated: true, completion: nil)

遷移元の処理:extensionで以下のように実装する

extension ViewController: UIAdaptivePresentationControllerDelegate {
    func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
    }
}

遷移先の処理:extensionで、以下のように実装する

extension ModalViewController {   
    override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
        super.dismiss(animated: flag, completion: completion)
        guard let presentationController = presentationController else {
            return
        }
        presentationController.delegate?.presentationControllerDidDismiss?(presentationController)
    }
}

これで、presentationControllerDidDismissに処理を書くと、呼ばれるようになります。

実際にpresentationControllerDidDismissで実装する方法で実装してみる

STEP.1
遷移の記述に以下のdelegateを追加する
@IBAction func toNextBtn(_ sender: Any) {
    let nextView = storyboard?.instantiateViewController(identifier: "Next") as! NextViewController
    nextView.presentationController?.delegate = self //←追加する
    present(nextView, animated: true, completion: nil)
}

画面遷移の仕方がわからない方は、こちらの記事をオススメします。

【Swift5/Xcode】画面遷移のチートシート。Segueを画面遷移とSegueを使わない画面遷移を徹底解説
STEP.2
以下のextensionを追加する
extension ViewController: UIAdaptivePresentationControllerDelegate {
    func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
        //処理
        self.view.backgroundColor = UIColor.red
    }
}

やりたい処理をこのメソッドの中に書いてください。

STEP.3
遷移先に以下のextensionを追加する
extension NextViewController {
    override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
        super.dismiss(animated: flag, completion: completion)
        guard let presentationController = presentationController else {
            return
        }
        presentationController.delegate?.presentationControllerDidDismiss?(presentationController)
    }
}
完了
これで呼ばれると思います。

まとめ

今回は、iOS13以降で、モーダル表示の変更についての記事を書きました。

iOS12からiOS13への変更で大きく変わったのは、ダークモード対応と、このモーダル表示です。

ダークモード対応についての記事も以前に書いてあるので、みてみてください。

【Swift5/Xcode】縦画面固定、ダークモード無効化、iPadでiPhone表示。毎回忘れるので、記事に残しておきます。