With iOS 12, Apple has introduced Network, a framework that includes the NWPathMonitor
class. NWPathMonitor
gives us the means to monitor changes of state in the internet connection. If you ever used Apple’s older Reachability
(prior to iOS 12) system, NWPathMonitor
replaces it fully.
NWPathMonitor
To use this new way to check the status of the internet connection, we first need to create an instance of NWPathMonitor
:
let monitor = NWPathMonitor()
We can also instantiate the NWPathMonitor
class indicating a particular type of network that we want to check. For example, to check WiFi connections:
let monitor = NWPathMonitor(requiredInterfaceType: .wifi)
NWPathMonitor
can check different types of interfaces:
cellular
for 3G / 4G connectionsloopback
for localhostother
for virtual networks or unknown network typeswifi
for WiFi connectionswiredEthernet
. If the device is connected to the internet by cable.Detection of changes in the state of the internet connection are made through the pathUpdateHandler
property:
monitor.pathUpdateHandler = { path in if path.status == .satisfied { print("There is internet") } else { print("No internet") } }
NWPath has a few properties, but there are two in particular you’re likely to care about: status
describes whether the connection is currently available or not, and isExpensive
is set to true when using cellular data or when using WiFi that is hotspot routed through an iPhone’s cellular connection.
unsatisfied
. The connection (path) cannot be used.satisfied
. The connection (path) has been established and allows data to be sent.requiresConnection
. The connection (path) is not currently available, but if a new connection is established it can be activated.In order to start receiving information about changes in the state of the internet connection, we need to call the start()
method. The start()
method needs a queue to do this job:
let queue = DispatchQueue(label: "Monitor") monitor.start(queue: queue)
Once we no longer need to know the changes in the state of the internet connection, we will call the cancel()
method.
Let's write Singleton class to collect information about network status
import Network public enum ConnectionType { case wifi case ethernet case cellular case unknown } class NetworkStatus { static public let shared = NetworkStatus() private var monitor: NWPathMonitor private var queue = DispatchQueue.global() var isOn: Bool = true var connType: ConnectionType = .wifi val listener: () -> Void private init() { self.monitor = NWPathMonitor() self.queue = DispatchQueue.global(qos: .background) self.monitor.start(queue: queue) } func start() { self.monitor.pathUpdateHandler = { path in self.isOn = path.status == .satisfied self.connType = self.checkConnectionTypeForPath(path) } } func stop() { self.monitor.cancel() } func checkConnectionTypeForPath(_ path: NWPath) -> ConnectionType { if path.usesInterfaceType(.wifi) { return .wifi } else if path.usesInterfaceType(.wiredEthernet) { return .ethernet } else if path.usesInterfaceType(.cellular) { return .cellular } return .unknown } }
Example of usage
let net = NetworkStatus.shared net.start() // Internet connection monitoring starts net.cancel() // Internet connection monitoring stops let status = net.connType // Returns the connection type
Reachability
If your app supports iOS versions before iOS 12, you’ll want to use the older Reachability component. It uses the SCNetworkReachability
class to create a network socket, and to listen for changes.
We can use Reachability
as follows. First, we’ll create a closure like this:
let onUpdate = { reachability in if reachability.connection == .wifi { print("We have WiFi!") } else if reachability.connection == .cellular { print("We have 3G/4G!") } else { print("No internet :-(") } }
Then, we’re creating a Reachability
object and assign the onUpdate
closure to two of its properties:
let reachability = Reachability() reachability?.whenReachable = onUpdate reachability?.whenUnreachable = onUpdate
The closure we defined earlier is now called whenever the network connectivity status changes.
Finally, we need to start the reachability component to get connectivity updates. Here’s how:
do { try reachability.startNotifier() } else { print("Error starting Reachability...") }