You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 20:05:17