49040


Xcode10.0
swiftで、`ViewController`に、別の`ViewController`をポップアップウインドウのようにように表示しています。  
別の`ViewController`からは`dismiss(animated: true, completion:
nil)`で元の`ViewContoroller`で戻っています。

  * 別の`ViewController`の`Presentation`が`FullScreen`だと元の`ViewController`の`viewWillAppear`が呼び出されます
  * 別の`ViewController`の`Presentation`が`OverCurrentContext`だと元の`ViewController`の`viewWillAppear`が呼び出されません

`viewWillAppear`が呼び出されない理屈はわかりますが、`Presentation`が`OverCurrentContext`でも`viewWillAppear`を呼び出す方法をどちらかご教授ください。


CC BY-SA 4.0
2018-10-07T08:02:25.850
49034
2018-10-09T06:48:16.483
2018-10-09T06:48:16.483
19110
21142
question
swift ios xcode swift4
ViewControllerのPresentationがOverCurrentContexだと元のViewContorollerに戻った時にviewWillAppearが呼び出されない


すでにお分かりの通り、提示スタイルに`.overCurrentContext`を指定すると、子画面表示の時に`viewWillDisappear`も呼ばれませんし、子画面から戻ってきたときに`viewWillAppear`も呼ばれません。

従って、あなたのアプリのコードに、`viewWillAppear`を呼ぶような内容を記述してやる必要があります。

`dismiss(animated: true, completion:
nil)`のように`completion`引数を`nil`にしてしまわずに、なんらかの処理を行うクロージャを渡してやればそこに`dismiss`処理完了後に行う処理を記述できます。

例えばこんな感じ。

[code]

    @IBAction func dismissPressed(_ sender: UIButton) {
        let pvc = self.presentingViewController
        dismiss(animated: true) {
            pvc?.viewWillAppear(false)
        }
    }
    
[/code]

ただ、iOSのシステム側から呼び出されるのが前提のメソッドをアプリ内から明示的に呼び出すと、思わぬ副作用が出る場合があります。可能であれば、`viewWillAppear`から、あなたが呼び出したい処理だけを切り出して別メソッドとして、`dismiss`の`completion`クロージャの中では、そちらを呼び出すようにした方が良いかもしれません。

とりあえず上記のようなコードであなたが所望の動作が実現できるかどうか、お試しください。


CC BY-SA 4.0
2018-10-07T08:44:26.627
49035
2018-10-07T08:44:26.627
13972
49034
answer


`UIViewController`の`beginAppearanceTransition(_:animated:)`と`endAppearanceTransition()`を呼ぶことで、ビューコントローラの表示非表示が変わったことを伝えることができます。

本来はコンテナビューコントローラから内包する子のコントローラにライフサイクルを伝播させるためのメソッドですが、方向が逆になるだけで本来の使い方と同等なのでワークアラウンドとしては妥当なところでしょう。

仮に、単に`present(_:animated:completion:)`メソッドでビューコントローラを表示しているだけなら、表示される側のビューコントローラの各ライフサイクルメソッドの中で次のような順序でこのメソッドを呼び出せば、`modalPresentationStyle
= .fullScreen`の場合と同じ結果が得られます。

トランジションをカスタマイズしている場合は、トランジションの開始と終了の時点で適切にこれらのメソッドを呼び出します。

[code]

    class ViewController2: UIViewController {
        override func viewWillAppear(_ animated: Bool) {
            presentingViewController?.beginAppearanceTransition(false, animated: animated)
            super.viewWillAppear(animated)
        }
    
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
            presentingViewController?.endAppearanceTransition()
        }
    
        override func viewWillDisappear(_ animated: Bool) {
            super.viewWillDisappear(animated)
            presentingViewController?.beginAppearanceTransition(true, animated: animated)
            presentingViewController?.endAppearanceTransition()
        }
    
        override func viewDidDisappear(_ animated: Bool) {
            super.viewDidDisappear(animated)
        }
        ...
    
[/code]


CC BY-SA 4.0
2018-10-07T13:36:49.090
49040
2018-10-07T13:36:49.090
5519
49034
answer