咨询: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
相关产品推荐
相关产品推荐

