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

咨询:iPhone端网络连接检查函数的统一实现位置

统一实现iPhone网络连接检查的最优方案

嘿,这个场景我太熟悉了——重复写代码不仅麻烦,还容易留下维护隐患。完全不用在每个ViewController里堆viewWillAppear的网络检查逻辑,咱们用统一封装+全局触发的方式搞定,覆盖你提到的所有场景:

第一步:先封装一个全局网络监听工具类

首先搞一个单例的NetworkMonitor,用苹果官方推荐的NWPathMonitor(iOS 12+支持)来统一监听网络状态。这样所有地方都能复用同一个网络状态源,不会出现不一致的情况:

import Network
import Combine

class NetworkMonitor: ObservableObject {
    // 单例,全局唯一实例
    static let shared = NetworkMonitor()
    
    private let monitor: NWPathMonitor
    private let monitoringQueue = DispatchQueue(label: "NetworkMonitoringQueue")
    
    // 用@Published发布网络连接状态,方便其他地方订阅
    @Published var isNetworkConnected: Bool = false
    
    private init() {
        monitor = NWPathMonitor()
        // 在后台队列监听网络变化,避免阻塞主线程
        monitoringQueue.async {
            self.monitor.pathUpdateHandler = { path in
                // 切回主线程更新UI相关的状态
                DispatchQueue.main.async {
                    self.isNetworkConnected = path.status == .satisfied
                }
            }
            self.monitor.start(queue: self.monitoringQueue)
        }
    }
    
    deinit {
        monitor.cancel()
    }
}

这个类的核心作用是:全局监听网络状态变化,并通过@Published把状态同步给所有订阅者,不用每个地方都自己写监听逻辑。

第二步:处理两个触发场景

场景1:App从多任务切回前台(回到App时)

这个逻辑可以统一放在AppDelegate或者SceneDelegate(iOS 13+)的激活回调里,不用分散到各个VC:

如果你用的是AppDelegate(iOS 12及以下,或不支持多场景的App):

func applicationDidBecomeActive(_ application: UIApplication) {
    // 切回前台时检查网络
    handleNetworkStatus()
}

private func handleNetworkStatus() {
    guard !NetworkMonitor.shared.isNetworkConnected else { return }
    // 弹出网络异常提示,这里需要获取当前顶层ViewController
    let alert = UIAlertController(title: "网络异常", message: "请检查你的网络连接状态", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "知道了", style: .default))
    
    if let topVC = UIApplication.shared.windows.first?.rootViewController?.topMost() {
        topVC.present(alert, animated: true)
    }
}

// 扩展UIViewController,方便获取顶层VC
extension UIViewController {
    func topMost() -> UIViewController {
        if let presentedVC = presentedViewController {
            return presentedVC.topMost()
        }
        return self
    }
}

如果你用的是SceneDelegate(iOS 13+支持多场景的App):

func sceneDidBecomeActive(_ scene: UIScene) {
    handleNetworkStatus()
}

// handleNetworkStatus方法和上面完全一样,直接复用

场景2:ViewController展示时检查网络

不想每个VC都写viewWillAppear?有两个优雅的方案:

方案A:创建基类ViewController(推荐,适合大部分场景)

让所有需要检查网络的VC继承这个基类,一次性把逻辑写好:

class BaseNetworkCheckVC: UIViewController {
    private var cancellables = Set<AnyCancellable>()
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // 展示时直接检查当前网络状态
        checkNetworkConnection()
    }
    
    private func checkNetworkConnection() {
        guard !NetworkMonitor.shared.isNetworkConnected else { return }
        showNetworkErrorAlert()
    }
    
    private func showNetworkErrorAlert() {
        let alert = UIAlertController(title: "网络异常", message: "请检查你的网络连接", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "确定", style: .default))
        present(alert, animated: true)
    }
    
    // 可选:实时监听网络状态变化,比如用户在当前VC时网络突然断开
    override func viewDidLoad() {
        super.viewDidLoad()
        NetworkMonitor.shared.$isNetworkConnected
            .receive(on: DispatchQueue.main)
            .sink { [weak self] isConnected in
                if !isConnected {
                    self?.showNetworkErrorAlert()
                }
            }
            .store(in: &cancellables)
    }
}

然后你的业务VC直接继承这个基类就行:

class HomeViewController: BaseNetworkCheckVC {
    // 你的业务代码,不用管网络检查的事
}

方案B:协议+默认实现(灵活,适合特殊继承链的VC)

如果有些VC已经继承了其他基类(比如UITableViewController),用协议的方式更灵活:

// 定义协议
protocol NetworkCheckable: UIViewController {}

// 给协议加默认实现
extension NetworkCheckable {
    func checkNetworkOnViewAppear() {
        guard !NetworkMonitor.shared.isNetworkConnected else { return }
        let alert = UIAlertController(title: "网络异常", message: "请检查你的网络连接", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "确定", style: .default))
        self.present(alert, animated: true)
    }
}

然后在需要的VC里遵守协议,在viewWillAppear调用方法:

class ProfileTableViewController: UITableViewController, NetworkCheckable {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        checkNetworkOnViewAppear()
    }
}

额外优化建议

  • 如果你的App需要区分网络类型(比如WiFi/蜂窝网络),可以在NetworkMonitor里扩展NWPath的属性,比如isWiFiConnected;
  • 网络提示可以做成全局的Toast,比Alert更友好,不会打断用户操作;
  • 可以把网络检查逻辑和业务逻辑解耦,比如用通知中心或者Combine订阅,让需要处理网络变化的地方自己响应,而不是全局强制弹出提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:09:08