Лучший подход к решению проблемы с сетевым подключением - 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