统一的UIViewController“成为最前端”检测?

mat*_*att 11 cocoa-touch uiviewcontroller ios

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

  • 我的视图控制器呈现了另一个全屏视图控制器,现在已将其关闭

  • 我的视图控制器显示了另一个不是全屏的视图控制器,现在已将其关闭

  • 我的视图控制器显示了一个弹出窗口,现在已将其关闭

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

在每种情况下,我的视图控制器都不再是“最前端”的视图控制器,然后再次变为“最前端”。我很好奇iOS没有向我的视图控制器发送涵盖所有这些情况的单一毯子“成为最前面”事件。

我想我可以互相覆盖的那些情况下独立了,我觉得这些都是我需要覆盖的情况下,但由此产生的代码混乱和分散:

  • viewDidAppear 检测推送视图控制器的弹出和全屏显示视图控制器的关闭

  • popover委托消息检测对popover的解雇

  • 不确定是什么原因导致非全屏显示视图控制器被解雇

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

mat*_*att 5

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

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()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 主页视图控制器必须采用家庭,并且必须设置每个视图控制器的homeself当礼物或推动它。

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

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        self.notifyComingHome()
    }
    
    Run Code Online (Sandbox Code Playgroud)

这适用于问题中列出的四种情况。可惜的是,Cocoa Touch不会自动为您完成此操作。


编辑由于iOS 13迫使非全屏显示视图控制器出现在我们的应用程序中,因此这种方法在我的应用程序中变得更加重要。另外,我将UIAlertController子类化,使其符合Away。

  • @AndreyGordeev 很好,给出更好的答案。我需要一个。 (4认同)
  • 此外,即使您在 iOS 13 上开始向下拖动模态视图控制器,也会调用“viewWillDisappear”。但是开始向下拖动 VC 并不意味着它将被忽略。 (2认同)