Swift中NetworkMonitor类网络连接状态更新异常如何修复?
修复NWPathMonitor网络状态检测反转及更新异常问题
问题根源分析
- 状态通知时机错误:当前代码在修改
isConnected和connectionType后才发送objectWillChange通知,不符合ObservableObject规范,可能导致UI无法正确捕获状态变化。 - 初始状态打印无效:
startMonitoring末尾的打印语句在pathUpdateHandler异步回调执行前触发,输出的是初始默认值,无法反映真实网络状态。 - 未监听状态变化:仅在
viewDidAppear中单次判断isConnected,未通过@ObservedObject或@StateObject监听状态变更,导致网络状态变化时UI无法自动更新。
修复方案
1. 用@Published自动管理状态通知
将isConnected和connectionType改为@Published属性,无需手动调用objectWillChange.send(),系统会自动在属性变更时发送通知。
2. 修正状态更新逻辑
将状态打印移至pathUpdateHandler内部,确保输出最新值;所有属性更新切换到主线程执行,保证UI线程安全。
3. 在View中正确监听状态变化
使用@StateObject(iOS 14+)或@ObservedObject监听NetworkMonitor实例,让UI自动响应网络状态变化。
完整修复后的代码
import Foundation import Network final class NetworkMonitor: ObservableObject { static let shared = NetworkMonitor() private let queue = DispatchQueue(label: "Network.Monitor") private let monitor: NWPathMonitor @Published public private(set) var isConnected: Bool = false @Published public private(set) var connectionType: ConnectionType = .unknown enum ConnectionType: String { case wifi case cellular case ethernet case unknown } private init() { monitor = NWPathMonitor() } public func startMonitoring() { monitor.pathUpdateHandler = { [weak self] path in guard let self = self else { return } let newIsConnected = path.status == .satisfied let newConnectionType = self.getConnectionType(for: path) DispatchQueue.main.async { self.isConnected = newIsConnected self.connectionType = newConnectionType print("@@34355 网络连接状态: \(self.isConnected),连接类型: \(self.connectionType.rawValue)") } } monitor.start(queue: queue) } public func stopMonitoring() { monitor.cancel() } private func getConnectionType(for path: NWPath) -> ConnectionType { if path.usesInterfaceType(.wifi) { return .wifi } else if path.usesInterfaceType(.cellular) { return .cellular } else if path.usesInterfaceType(.wiredEthernet) { return .ethernet } else { return .unknown } } }
View中正确使用示例
SwiftUI场景
import SwiftUI struct NetworkStatusView: View { @StateObject private var networkMonitor = NetworkMonitor.shared var body: some View { VStack(spacing: 16) { Text(networkMonitor.isConnected ? "已连接网络" : "未连接网络") .foregroundColor(networkMonitor.isConnected ? .green : .red) Text("连接类型: \(networkMonitor.connectionType.rawValue)") } .onAppear { networkMonitor.startMonitoring() } } }
UIKit场景
import UIKit import Combine class NetworkStatusViewController: UIViewController { private let networkMonitor = NetworkMonitor.shared private var cancellables = Set<AnyCancellable>() override func viewDidLoad() { super.viewDidLoad() networkMonitor.$isConnected .receive(on: DispatchQueue.main) .sink { [weak self] isConnected in self?.title = isConnected ? "已联网" : "无网络" } .store(in: &cancellables) } }
额外注意事项
- 模拟器测试:部分模拟器版本的网络状态检测可能存在延迟,建议在真实设备上验证功能。
- 生命周期管理:在App启动时调用
startMonitoring(),退出时调用stopMonitoring()避免资源泄漏。 - 线程安全:所有UI相关的状态更新必须在主线程执行,防止出现界面异常。
内容的提问来源于stack exchange,提问作者Christine
相关产品推荐
相关产品推荐

