统一 UIViewController "became frontmost" 检测?
Unified UIViewController "became frontmost" detection?
在我看来,这些情况都是平行的:
我的视图控制器显示了另一个全屏视图控制器,现在已关闭
我的视图控制器显示了另一个非全屏视图控制器,现在已被关闭
我的视图控制器显示了一个弹出窗口,现在已关闭
我的视图控制器推送了另一个视图控制器,现在已经弹出了
在每种情况下,我的视图控制器都不再是 "frontmost" 视图控制器,然后又变成了 "frontmost"。我觉得很好奇 iOS 没有单一的 "became frontmost" 事件发送到我的视图控制器来涵盖所有这些情况。
我想我可以单独涵盖每个案例,而且我认为这些都是我需要涵盖的所有案例,但生成的代码混乱且分散:
viewDidAppear
检测到推送视图控制器的弹出和全屏显示视图控制器的关闭
弹出窗口委托消息检测到弹出窗口的关闭
不确定是什么检测到非全屏显示视图控制器的关闭
人们如何连贯而优雅地处理这个问题?
这些案例的共同点不是原始视图控制器的出现,而是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 时调用该方法。
在我看来,这些情况都是平行的:
我的视图控制器显示了另一个全屏视图控制器,现在已关闭
我的视图控制器显示了另一个非全屏视图控制器,现在已被关闭
我的视图控制器显示了一个弹出窗口,现在已关闭
我的视图控制器推送了另一个视图控制器,现在已经弹出了
在每种情况下,我的视图控制器都不再是 "frontmost" 视图控制器,然后又变成了 "frontmost"。我觉得很好奇 iOS 没有单一的 "became frontmost" 事件发送到我的视图控制器来涵盖所有这些情况。
我想我可以单独涵盖每个案例,而且我认为这些都是我需要涵盖的所有案例,但生成的代码混乱且分散:
viewDidAppear
检测到推送视图控制器的弹出和全屏显示视图控制器的关闭弹出窗口委托消息检测到弹出窗口的关闭
不确定是什么检测到非全屏显示视图控制器的关闭
人们如何连贯而优雅地处理这个问题?
这些案例的共同点不是原始视图控制器的出现,而是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 时调用该方法。