web-dev-qa-db-ja.com

統一されたUIViewControllerが「最前線」の検出になりましたか?

私の考えでは、これらの状況はすべて同じです:

  • ビューコントローラーが別のビューコントローラーフルスクリーンを表示しましたが、これは現在閉じられています

  • 私のビューコントローラーはフルスクリーンではない別のビューコントローラーを提示しましたが、これは現在閉じられています

  • 私のビューコントローラーはポップオーバーを提示しましたが、今はそれが却下されました

  • 私のビューコントローラーは別のビューコントローラーを押しましたが、これは現在ポップされています

いずれの場合も、私のビューコントローラは「最前面」のビューコントローラでなくなり、その後再び「最前面」になりました。 iOSには、これらすべての状況をカバーするビューコントローラーに送信される単一の包括的な「最前線になる」イベントがないことに不思議に思います。

私はそれらのケースをそれぞれカバーできると思います個別にそして、それらはカバーする必要があるすべてのケースだと思いますが、結果のコードは混乱して散在しています:

  • viewDidAppearは、プッシュされたビューコントローラーのポップとフルスクリーンで表示されたビューコントローラーの終了を検出します

  • ポップオーバーデリゲートメッセージがポップオーバーの却下を検出

  • フルスクリーンで表示されないビューコントローラーの終了を検出するものがわからない

人々はこれをどのように首尾一貫してエレガントに扱うのでしょうか?

20
matt

ケースに共通するのは、元のビューコントローラーの外観ではなく、表示/プッシュされたビューコントローラーの非表示です。したがって、シンプルで明確なソリューションの1つは、プロトコルとデリゲートのアーキテクチャのようです。次のように、1組のプロトコルを宣言します。

protocol Home : class {
    func comingHome()
}
protocol Away : class {
    var home : Home? {get set}
}
extension Away where Self : UIViewController {
    func notifyComingHome() {
        if self.isBeingDismissed || self.isMovingFromParent {
            self.home?.comingHome()
        }
    }
}
  • ホームビューコントローラーはホームを採用する必要があり、表示またはプッシュするときに、各ビューコントローラーのhomeselfに設定する必要があります。

  • 提示またはプッシュされたView Controllerは、Awayを採用し、viewWillDisappearを次のように実装する必要があります。

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        self.notifyComingHome()
    }
    

これは、質問にリストされている4つのケースで機能します。ただし、Cocoa Touchがこれを自動的に実行しないのは残念です。


[〜#〜] edit [〜#〜] iOS 13が非フルスクリーン表示のビューコントローラーを強制するようになったため、私のアプリではこのアプローチがさらに重要になっています。また、UIAlertControllerをサブクラス化して、Awayに準拠するようにしました。

8
matt

1つの解決策は、MVVM-Cスタイルのアーキテクチャのように、コーディネーターアプローチを取ることです。 VCのビュー階層を直接変更することはありませんが、常にCoordinatorを呼び出してそれを実行します。coordinator.showDetails(...)

さらに、VCに戻るときにコーディネーターが呼び出すことができるviewDidBecomeForemostメソッドをVCで定義します。

0
NSRover