统一 UIViewController "became frontmost" 检测?

Unified UIViewController "became frontmost" detection?

在我看来,这些情况都是平行的:

在每种情况下,我的视图控制器都不再是 "frontmost" 视图控制器,然后又变成了 "frontmost"。我觉得很好奇 iOS 没有单一的 "became frontmost" 事件发送到我的视图控制器来涵盖所有这些情况。

我想我可以单独涵盖每个案例,而且我认为这些都是我需要涵盖的所有案例,但生成的代码混乱且分散:

人们如何连贯而优雅地处理这个问题?

这些案例的共同点不是原始视图控制器的出现,而是presented/pushed视图控制器的消失。因此,一种简单明了的解决方案似乎是协议和委托架构。声明一对协议,如下:

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()
        }
    }
}
  • home view controller必须采用Home,并且在present或push时必须将每个view controller的home设置为self

  • 呈现或推送的视图控制器必须采用Away,并且必须实现viewWillDisappear如下:

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

这适用于问题中列出的四种情况。遗憾的是,Cocoa Touch 不会自动为您执行此操作。


编辑 这种方法在我的应用程序中变得更加重要,因为 iOS 13 已经强制我们使用非全屏呈现的视图控制器。此外,我将 UIAlertController 子类化,使其符合 Away.

一种解决方案可能是采用协调器方法,就像在 MVVM-C 风格的架构中一样。您永远不会直接更改 VC 中的视图层次结构,但总是调用协调器为您做这件事。 coordinator.showDetails(...)

此外,您在 VC 中定义了一个 viewDidBecomeForemost 方法,协调器可以在返回 VC 时调用该方法。