How to track network connection status in Swift? Hello, native implementation, bye, Reachability By Zoranin Tutorials - April 23, 2022 Comments: 0 Views: 855 Most of the implementations you can find for monitoring the network connection of your iOS device rely on third party dependencies such as Reachability , NetworkReachabilityManagerin Alamofire, or utilities that periodically send HTTP requests to determine the status of the network connection. Instead, I'd like to present an alternative approach that uses the native framework introduced in iOS 12. For this implementation, we only need the Network. Although you would normally use it when you need direct access to protocols such as TLS , TCP and UDP , we won't do anything too complicated here. Initial Implementation Let's start building our NetworkMonitor utility : import Network final class NetworkMonitor { static let shared = NetworkMonitor() private let monitor: NWPathMonitor private init() { monitor = NWPathMonitor() } } Here NWPathMonitor is an observer that will monitor the state of the network connection and respond to changes that may occur. Next, we'll create a few properties to hold the current state of the network connection: final class NetworkMonitor { static let shared = NetworkMonitor() private let monitor: NWPathMonitor private(set) var isConnected = false /// The next property is needed to check that the network connection /// will be expensive in terms of traffic consumption /// /// Cellular interfaces are considered expensive. WiFi hotspot /// from other devices can also be expensive. Other interfaces /// may be expensive in the future private(set) var isExpensive = false private(set) var currentConnectionType: NWInterface.InterfaceType? private init() { monitor = NWPathMonitor() } } Since these properties can only be read-only, private(set) . We clearly don't want this lengthy task to run on our application's main thread, so we'll create a new DispatchQueue to manage this task: private let queue = DispatchQueue(label: "NetworkConnectivityMonitor") The network framework defines an enum NWInterface.InterfaceTypethat contains all the media types that our device can support (WiFi, cellular, wired ethernet, etc.). Because this enum is declared in ObjC, we don't have access to the property allCases, as is the case with enums in Swift, for example. So let's add protocol compliance CaseIterableand implement allCases. As a result of this extra step, the rest of our implementation will be much simpler and much more readable. extension NWInterface.InterfaceType: CaseIterable { public static var allCases: [NWInterface.InterfaceType] = [ .other, .wifi, .cellular, .loopback, .wiredEthernet ] } The last step in our implementation is to create functions responsible for starting and stopping the monitoring process: func startMonitoring() { monitor.pathUpdateHandler = { [weak self] path in self?.isConnected = path.status != .unsatisfied self?.isExpensive = path.isExpensive // Identifies the current connection type from the // list of potential network link types self?.currentConnectionType = NWInterface.InterfaceType.allCases.filter { path.usesInterfaceType($0) }.first } monitor.start(queue: queue) } func stopMonitoring() { monitor.cancel() } NetworkMonitor in action Tracking can be started from anywhere in the code by simply calling NetworkMonitor.shared.startMonitoring(), although in most cases you'll want to initiate this process in AppDelegate. We can then use NetworkMonitor.shared.isConnectedto check the status of our network connection in real time. Here is our implementation so far: import Network extension NWInterface.InterfaceType: CaseIterable { public static var allCases: [NWInterface.InterfaceType] = [ .other, .wifi, .cellular, .loopback, .wiredEthernet ] } final class NetworkMonitor { static let shared = NetworkMonitor() private let queue = DispatchQueue(label: "NetworkConnectivityMonitor") private let monitor: NWPathMonitor private(set) var isConnected = false private(set) var isExpensive = false private(set) var currentConnectionType: NWInterface.InterfaceType? private init() { monitor = NWPathMonitor() } func startMonitoring() { monitor.pathUpdateHandler = { [weak self] path in self?.isConnected = path.status != .unsatisfied self?.isExpensive = path.isExpensive self?.currentConnectionType = NWInterface.InterfaceType.allCases.filter { path.usesInterfaceType($0) }.first } monitor.start(queue: queue) } func stopMonitoring() { monitor.cancel() } } Add NotificationCenter Support The behavior of modern iOS apps changes drastically when a device's network connection is disconnected—some screens may notify you that the device has lost connection, the app's caching behavior may change, or even some user scripts may break. To support this type of behavior, we need to extend our implementation to send notifications throughout the application when the connection status changes. import Foundation import Network extension Notification.Name { static let connectivityStatus = Notification.Name(rawValue: "connectivityStatusChanged") } extension NWInterface.InterfaceType: CaseIterable { public static var allCases: [NWInterface.InterfaceType] = [ .other, .wifi, .cellular, .loopback, .wiredEthernet ] } final class NetworkMonitor { static let shared = NetworkMonitor() private let queue = DispatchQueue(label: "NetworkConnectivityMonitor") private let monitor: NWPathMonitor private(set) var isConnected = false private(set) var isExpensive = false private(set) var currentConnectionType: NWInterface.InterfaceType? private init() { monitor = NWPathMonitor() } func startMonitoring() { monitor.pathUpdateHandler = { [weak self] path in self?.isConnected = path.status != .unsatisfied self?.isExpensive = path.isExpensive self?.currentConnectionType = NWInterface.InterfaceType.allCases.filter { path.usesInterfaceType($0) }.first NotificationCenter.default.post(name: .connectivityStatus, object: nil) } monitor.start(queue: queue) } func stopMonitoring() { monitor.cancel() } } // ViewController.swift class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(showOfflineDeviceUI(notification:)), name: NSNotification.Name.connectivityStatus, object: nil) } @objc func showOfflineDeviceUI(notification: Notification) { if NetworkMonitor.shared.isConnected { print("Connected") } else { print("Not connected") } } } All source code is here . Network Link Conditioner Since we are talking about network technologies and debugging connection problems, it's time to mention Network Link Conditioner. With this tool, you can simulate various network conditions on a computer and, accordingly, in an iOS simulator. With this tool, we can not only monitor extreme situations when we are completely online or offline, but also test the behavior of our application in various network conditions. You can download it from the Apple developers site or from this link . The utility itself will be located in the Hardware folder, just click on it to install it. After that, you can configure the settings you need, just like on a real device here: Useful Resources An article with an analysis of an example application for tracking a network connection. Work example for Network Link Conditioner Page with additional utilities from Apple.
Jetpack Compose in React Native Projects: Pros, Cons, and Integration Today I will tell you why Jetpack Compose is needed in React Native projects and share my March 29, 2022 Tutorials
Why Reactive Programming in Swift? Improving code readability Everyone knows about the nightmarish closures in Swift. Due to the February 20, 2022 Tutorials
How to develop your first app with React Native I want to talk a little about what React Native is, why it is important and popular now, and January 24, 2022 Tutorials