【问题标题】:Crash on iOS 16+ _nw_path_evaluator_call_update_handler_block_invoke NWPathMonitor.pathUpdateHandler callback in Network framework of apple在 iOS 16+ 上崩溃
【发布时间】:2022-12-20 18:57:02
【问题描述】:

尝试使用苹果的网络框架监控 iOS 应用程序中的网络变化。

import Foundation
import Network

protocol NWPathMonitorInterface {
    var pathUpdateHandler: ((_ newPath: NWPath) -> Void)? {get set}
    func start(queue: DispatchQueue)
    func cancel()
}

extension NWPathMonitor: NWPathMonitorInterface {}

final class ReachabilityManager {
   
   private(set) var isNetworkAvailable: Bool = false
   private(set) var connectionType: NWInterface.InterfaceType?
   
   private let queue: DispatchQueue
   private var monitor: NWPathMonitorInterface?
   
   public var onUpdateNetworkStatus: ((Bool) -> Void)?
   static let shared = ReachabilityManager(monitor: NWPathMonitor(),
                                           queue: DispatchQueue(label: "com.rapido.networkMonitoring"))

   deinit {
       stopMonitoring()
   }
   
   init(monitor: NWPathMonitorInterface,
        queue: DispatchQueue) {
       self.monitor = monitor
       self.queue = queue
   }
   
   enum ConnectionType {
       case wifi
       case cellular
       case ethernet
   }
   
   public func startMonitoring() {
       if monitor == nil {
           monitor = NWPathMonitor()
       }
       self.monitor?.start(queue: queue)
       self.monitor?
           .pathUpdateHandler = { [weak self] path in
               guard let self = self else { return }
               self.updateStatus(status: path.status)
               self.updateConnectionType(interface: path
                   .availableInterfaces
                   .map(\.type))
       }
   }
   
   
   func updateStatus(status: NWPath.Status) {
       isNetworkAvailable = status == .satisfied ? true : false
       onUpdateNetworkStatus?(isNetworkAvailable)
   }
   
   func updateConnectionType(interface: [NWInterface.InterfaceType]) {
       connectionType = interface.first
   }
   
   func stopMonitoring() {
       monitor?.cancel()
       monitor = nil
   }
}

当应用程序状态变为前台时开始监控,当应用程序进入后台时停止监控

 func applicationDidBecomeActive(_ application: UIApplication) {
          ReachabilityManager.shared.startMonitoring()
 }

 func applicationDidEnterBackground(_ application: UIApplication) {
        ReachabilityManager.shared.stopMonitoring()
 }

添加崩溃日志

Crashed: com.apple.root.default-qos
0  libswiftCore.dylib             0x3da1bc _swift_release_dealloc + 32
1  libswiftNetwork.dylib          0x372a4 closure #1 in NWPathMonitor.init(requiredInterfaceType:) + 296
2  libswiftNetwork.dylib          0x2470 thunk for @escaping @callee_guaranteed (@guaranteed OS_nw_path) -> () + 52
3  Network                        0x91dad8 __nw_path_evaluator_call_update_handler_block_invoke + 336
4  libdispatch.dylib              0x24b4 _dispatch_call_block_and_release + 32
5  libdispatch.dylib              0x3fdc _dispatch_client_callout + 20
6  libdispatch.dylib              0x70c8 _dispatch_queue_override_invoke + 788
7  libdispatch.dylib              0x15a6c _dispatch_root_queue_drain + 396
8  libdispatch.dylib              0x16284 _dispatch_worker_thread2 + 164
9  libsystem_pthread.dylib        0xdbc _pthread_wqthread + 228
10 libsystem_pthread.dylib        0xb98 start_wqthread + 8

关于崩溃的一件奇怪的事情只发生在 iOS 16+ 设备和 23% 的后台状态。由于频率非常低,我仍然无法在本地重现此内容。任何帮助表示赞赏。

【问题讨论】:

    标签: ios swift crash ios16


    【解决方案1】:

    尽管没有复制给我,但似乎 NWMonitor 的实例在某些边缘获得了 dealloc。使用 isMonitoring 标志增加更多理智。现在它是 100% 无崩溃。

    更新代码

    import Network
    
    protocol NWPathMonitorInterface {
         var pathUpdateHandler: ((_ newPath: NWPath) -> Void)? {get set}
         func start(queue: DispatchQueue)
         func cancel()
         var currentPath: NWPath { get }
    }
    
    extension NWPathMonitor: NWPathMonitorInterface {}
    
    final class ReachabilityManager {
        
        private(set) var isNetworkAvailable: Bool = false
        private(set) var connectionType: NWInterface.InterfaceType?
        private(set) var isMonitoring: Bool = false
        
        private let queue: DispatchQueue
        private var monitor: NWPathMonitorInterface?
        
        public var onUpdateNetworkStatus: ((Bool) -> Void)?
        static let shared = ReachabilityManager(monitor: NWPathMonitor(),
                                                queue: DispatchQueue(label: "com.rapido.networkMonitoring"))
    
        deinit {
            stopMonitoring()
        }
        
        init(monitor: NWPathMonitorInterface,
             queue: DispatchQueue) {
            self.monitor = monitor
            self.queue = queue
        }
        
        enum ConnectionType {
            case wifi
            case cellular
            case ethernet
        }
        
        public func startMonitoring() {
            guard !isMonitoring else {
                return
            }
            if monitor == nil {
                monitor = NWPathMonitor()
            }
            self.monitor?.start(queue: queue)
            self.monitor?
                .pathUpdateHandler = { [weak self] status in
                    guard let self = self,
                          let monitor = self.monitor else { return }
                
                    self.updateStatus(status: monitor.currentPath.status)
                    self.updateConnectionType(interface: monitor.currentPath
                        .availableInterfaces
                        .map(.type))
            }
            isMonitoring = true
        }
        
        
        func updateStatus(status: NWPath.Status) {
            isNetworkAvailable = status == .satisfied ? true : false
            onUpdateNetworkStatus?(isNetworkAvailable)
        }
        
        func updateConnectionType(interface: [NWInterface.InterfaceType]) {
            connectionType = interface.first
        }
        
        func stopMonitoring() {
            monitor?.cancel()
            monitor = nil
            isMonitoring = false 
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-09-29
      • 2022-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-24
      相关资源
      最近更新 更多