统一 UIView控制器"became frontmost"检测?



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

  • 我的视图控制器提供了另一个视图控制器全屏,现在已经被驳回

  • 我的视图控制器提供了另一个不是全屏的视图控制器,它现在已经被驳回

  • 我的视图控制器显示了一个弹出窗口,现在已经被驳回

  • 我的视图控制器推了另一个视图控制器,现在已经弹出

在任何情况下,我的视图控制器都不再是"最前面"的视图控制器,然后又变成了"最前面的"。我觉得奇怪的是,iOS没有一个"成为最前沿"的事件发送到我的视图控制器,涵盖了所有这些情况。

我认为我可以单独覆盖中的每一个案例,我认为这些都是我需要覆盖的所有案例,但结果代码令人困惑和分散:

  • viewDidAppear检测到按下的视图控制器弹出和全屏显示的视图控制器消失

  • popover委托消息检测popover 的取消

  • 不确定是什么检测到非全屏显示的视图控制器被取消

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

这些情况的共同点不是原始视图控制器的出现,而是呈现/推送的视图控制器的消失。因此,一个简单明了的解决方案似乎是协议和委托体系结构。声明一对协议,如下所示:

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,并且在呈现或推送时必须将每个视图控制器的home设置为self

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

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

这适用于问题中列出的四种情况。遗憾的是,Cocoa Touch并没有自动为你做到这一点。


EDIT由于iOS 13强制我们使用非全屏显示的视图控制器,这种方法在我的应用程序中变得更加重要。此外,我还将UIAlertController细分为子类,使其符合Away。

一种解决方案可以像MVVM-C风格的体系结构一样采用Coordinator方法。在VC中,您从不直接更改视图层次结构,而是总是调用Coordinator来为您更改。coordinator.showDetails(…)

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

相关内容

  • 没有找到相关文章

最新更新