使用modalPresentationStyle=.formSheet时MainViewController的viewWillDisappear未触发
解决方案
首先明确:这种场景下系统不会触发MainViewController的viewWillDisappear,因为它的视图仍保留在主窗口的视图层级中(formSheet样式不会移除底层视图),只有当SheetViewController本身被dismiss时,MainViewController的生命周期方法才会响应。
如果不想用代理,可以试试以下几种方式:
1. 监听自定义通知
在SheetViewController即将present全屏视图控制器时,发送自定义通知,MainViewController监听该通知来停止请求:
// SheetViewController中 func presentFullScreenVC() { let fullScreenVC = FullScreenViewController() fullScreenVC.modalPresentationStyle = .fullScreen NotificationCenter.default.post(name: NSNotification.Name("MainVCShouldPauseRequests"), object: nil) present(fullScreenVC, animated: true) } // MainViewController中 override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(pauseRequests), name: NSNotification.Name("MainVCShouldPauseRequests"), object: nil) } @objc func pauseRequests() { // 停止后端请求的逻辑 } // 记得在deinit中移除观察者 deinit { NotificationCenter.default.removeObserver(self) }
2. 监听窗口的视图层级变化
通过监听UIWindow.didAddSubviewNotification,判断添加的子视图是否属于全屏视图控制器,进而触发MainViewController的停止逻辑:
// MainViewController中 override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(checkIfCovered), name: UIWindow.didAddSubviewNotification, object: UIApplication.shared.keyWindow) } @objc func checkIfCovered(notification: Notification) { guard let topVC = UIApplication.shared.keyWindow?.rootViewController?.presentedViewController else { return } // 判断顶部视图控制器是否为全屏样式 if topVC.modalPresentationStyle == .fullScreen { // 停止请求 } }
3. 利用Combine监听顶层视图控制器(iOS 13+)
使用Combine框架定时检查应用顶层视图控制器的变化,当顶层是全屏VC时停止请求:
import Combine class MainViewController: UIViewController { private var cancellables = Set<AnyCancellable>() override func viewDidLoad() { super.viewDidLoad() Timer.publish(every: 0.5, on: .main, in: .common) .autoconnect() .sink { [weak self] _ in self?.checkTopViewController() } .store(in: &cancellables) } private func checkTopViewController() { let topVC = UIApplication.shared.topViewController() if topVC is FullScreenViewController { // 停止请求 } } } // 扩展UIApplication获取顶层VC extension UIApplication { func topViewController() -> UIViewController? { var topVC = keyWindow?.rootViewController while let presentedVC = topVC?.presentedViewController { topVC = presentedVC } return topVC } }
4. 重写viewWillLayoutSubviews检查可见区域
在MainViewController中重写该方法,检查自身视图在屏幕上的可见区域,若完全被覆盖则停止请求:
override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() let visibleRect = view.convert(view.bounds, to: UIApplication.shared.keyWindow) let intersection = UIApplication.shared.keyWindow?.bounds.intersection(visibleRect) ?? .zero if intersection.isEmpty { // 视图完全被覆盖,停止请求 } else { // 视图可见,恢复请求(如果需要) } }
内容的提问来源于stack exchange,提问作者JRV
相关产品推荐
相关产品推荐

