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

Swift:在AppDelegate中获取当前UIViewController并处理断网UI问题

Fixing the Current View Controller Retrieval Issue on Network Disconnect

First off, great job getting your Reachability setup working for detecting network state changes! The problem you’re hitting with fetching the current view controller likely stems from your existing code not accounting for all possible view controller hierarchy scenarios—like tab bar controllers nested with navigation controllers, or modally presented view controllers.

Let’s break down what’s missing in your current code:

  • It only handles direct navigation controllers as the root, but if your root is a UITabBarController or a view controller has been presented modally, your code won’t catch the actual visible screen.
  • The optional binding for window is a bit fragile, since UIApplication.shared.delegate?.window returns an optional of an optional (UIWindow??).

Step 1: Create a Helper to Get the Topmost View Controller

Add this extension to UIApplication (you can drop it in a new Swift file or at the bottom of your AppDelegate.swift) to reliably fetch the current visible view controller, no matter the hierarchy:

extension UIApplication {
    func topMostViewController() -> UIViewController? {
        // Grab the active key window first
        guard let window = self.windows.first(where: { $0.isKeyWindow }) else { return nil }
        var topViewController = window.rootViewController
        
        // Traverse through any modally presented view controllers
        while let presentedViewController = topViewController?.presentedViewController {
            topViewController = presentedViewController
        }
        
        // Handle navigation controllers
        if let navigationController = topViewController as? UINavigationController {
            topViewController = navigationController.visibleViewController
        } 
        // Handle tab bar controllers (and nested nav controllers inside tabs)
        else if let tabBarController = topViewController as? UITabBarController {
            topViewController = tabBarController.selectedViewController
            if let tabNavVC = topViewController as? UINavigationController {
                topViewController = tabNavVC.visibleViewController
            }
        }
        
        return topViewController
    }
}

Step 2: Update Your Reachability Callback

Now modify your reachabilityChanged function to use this helper, then update the UI of the top view controller to notify the user:

@objc func reachabilityChanged(note: Notification) {
    let reachability = note.object as! Reachability
    
    if reachability.connection == .none {
        // Get the current visible view controller
        guard let currentVC = UIApplication.shared.topMostViewController() else { return }
        
        print("Current visible VC: \(currentVC)")
        
        // Example: Add a network error banner to the current VC's view
        let errorBanner = UIView(frame: CGRect(x: 0, y: -60, width: currentVC.view.frame.width, height: 60))
        errorBanner.backgroundColor = .systemRed
        errorBanner.tag = 999 // Use a tag to avoid duplicate banners
        
        // Remove existing banner if it's already there
        currentVC.view.viewWithTag(999)?.removeFromSuperview()
        
        let errorLabel = UILabel(frame: errorBanner.bounds)
        errorLabel.text = "Network connection lost!"
        errorLabel.textColor = .white
        errorLabel.textAlignment = .center
        errorBanner.addSubview(errorLabel)
        
        currentVC.view.addSubview(errorBanner)
        
        // Animate the banner into view
        UIView.animate(withDuration: 0.3) {
            errorBanner.frame.origin.y = 0
        }
    } else {
        // Optional: Remove the error banner when network is restored
        if let currentVC = UIApplication.shared.topMostViewController() {
            currentVC.view.viewWithTag(999)?.removeFromSuperview()
        }
    }
}

Why This Works

  • The topMostViewController helper first targets the key window (the one actively visible to the user), then traverses through any modally presented screens to get the frontmost one.
  • It handles both UINavigationController and UITabBarController hierarchies, including nested cases where a tab’s root is a navigation controller.
  • The UI update example adds a temporary banner, but you can replace this with your own custom alert, toast, or any UI change you need to notify the user.

内容的提问来源于stack exchange,提问作者Ahmed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:46:10