Лучший подход к решению проблемы с сетевым подключением - 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, object: nil)
    
    notificationCenter.addObserver(self, 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
}
}

Это работает нормально, но проблема в том, что всякий раз, когда я хочу использовать это в других контроллерах представления, мне приходится дублировать код для повторного назначения NetworkMonitor в appDidBecomeActive и делать его нулевым в appMovedToBackground .

Поэтому, пожалуйста, помогите мне улучшить мой подход, чтобы мне просто нужно было вызвать startMonitoring в контроллерах представления.

1 ответ

вы рассматривали методы applicationWillResignActive(_:) и applicationWillEnterForeground(_:)? Также, может быть, неплохо было бы сделать свой NetworkMonitor Синглтон и вызов stopMonitoring() и startMonitoring() в соответствующих методах UIApplicationDelegate

Другие вопросы по тегам