处理网络连接问题的最佳方法 - Swift 5

问题描述

我试图使用 Apple 提供的网络框架来实现网络连接,以便我们处理网络问题。

我所做的是: 1.每当应用程序进入活动状态时 - 我开始监控网络 2.每当应用程序进入后台 - 我取消了监控以降低电池电量

每当我进入后台并再次返回应用程序时,我遇到的问题就不会再次监视,因为我们无法再次分配监视器实例。 我们需要创建新的监控实例才能再次开始监控

我正在尽量减少冗余代码

所以要实现所有的边缘情况

以下是我的方法:-

网络监控文件

 import Foundation
 import Network

 final class NetworkMonitor {

private let monitor: NWPathMonitor =  NWPathMonitor()

public private(set) var isConnected:Bool = false

public private(set) var connectionType:ConnectionType = .unkNown

 init() {
    print("init")
    let queue = dispatchQueue.global(qos: .background)
    monitor.start(queue: queue)
}

public enum ConnectionType {
    case cellular
    case wifi
    case ethernet
    case unkNown
}


public func startMonitoring() {

    monitor.pathUpdateHandler = { [weak self] path in
        self?.isConnected = path.status == .satisfied
        self?.getConnectionType(path)
        NotificationCenter.default.post(name: NSNotification.Name("connectionType"),object: nil)
    }
   }

public func stopMonitoring() {
      monitor.cancel()
}

private func getConnectionType(_ path:NWPath) {
   
    if path.usesInterfaceType(.wifi) {
        connectionType = .wifi
    } else if path.usesInterfaceType(.cellular) {
        connectionType = .cellular
    } else if path.usesInterfaceType(.wiredEthernet) {
        connectionType = .ethernet
    } else {
        connectionType = .unkNown
    }
    
}

}

这是我想要监控的视图:

   class ViewController: UIViewController {

private var networkMonitor:NetworkMonitor?

private let notificationCenter = NotificationCenter.default
private let networkConnectivityView = NetworkConnectivityView()


override func viewDidLoad() {
    super.viewDidLoad()
    
    view.addSubview(networkConnectivityView)
    notificationCenter.addobserver(self,selector: #selector(listeningNetworkConnection),name: NSNotification.Name("connectionType"),object: nil)
    
    notificationCenter.addobserver(self,selector: #selector(appDidBecomeActive),name: UIApplication.didBecomeActiveNotification,selector: #selector(appMovedToBackground),name: UIApplication.willResignActiveNotification,object: nil)
    
}
  

@objc func appDidBecomeActive() {
    networkMonitor = NetworkMonitor()
    networkMonitor?.startMonitoring()
}

@objc func appMovedToBackground() {
    
    networkMonitor?.stopMonitoring()
    networkMonitor = nil
}

@objc private func listeningNetworkConnection() {
    dispatchQueue.main.async { [weak self] in
        self?.updateUI()
    }
}

private func updateUI() {
    
    guard let networkMonitor = networkMonitor else {
        return
    }
    
    if networkMonitor.isConnected{
        print("connected")
        networkConnectivityView.configure(with: "Connected")
    } else {
        print("Not connected")
        networkConnectivityView.configure(with: "Not Connected")
    }
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    
    networkConnectivityView.frame = CGRect(x: 0,y: 0,width: view.frame.size.width,height: 50)
    networkConnectivityView.center = view.center
}
}

这工作正常,但问题是每当我想在其他视图控制器中使用它时,我都必须复制代码以在 appDidBecomeActive 中再次分配 NetworkMonitor 并制作它appMovedToBackground 中的 nil。

所以请帮助我改进我的方法,以便我只需要在视图控制器中调用 startMonitoring

解决方法

您考虑过 UIApplicationDelegate 方法 applicationWillResignActive(_:)applicationWillEnterForeground(_:) 吗? 另外,让您的 NetworkMonitor 成为单例并在 stopMonitoring()

的相应方法中调用 startMonitoring()UIApplicationDelegate 也是一个好主意