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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 16:10:24