A minimal reachability check for Swift
Why do reachability checks?
Reachability checks are used to give us an indication about whether the device has a usable network connection. If the check returns false
, we can use that information to provide the user with better error.
How not to do reachability checks
Don't be tempted to use a reachability check to decide if to make an API call. All networking is unreliable - so reachability checks are, by definition, also unreliable. If you perform the check before the network call, and decide to not make that call, there's a risk you might be blocking a network call that may have succeeded.
A minimal reachability class in Swift
import Foundation
import Network
final class NetworkReachability {
static let shared = NetworkReachability()
private(set) var isReachable: Bool = false
private let pathMonitor: NWPathMonitor = NWPathMonitor()
private init() {
self.pathMonitor.pathUpdateHandler = { [weak self] path in
self?.handleUpdate(path)
}
self.pathMonitor.start(queue: DispatchQueue.global(qos: .utility))
}
private func handleUpdate(_ path: NWPath) {
switch path.status {
case .satisfied:
self.isReachable = true
case .unsatisfied, .requiresConnection:
self.isReachable = false
@unknown default:
self.isReachable = false
}
}
}
This utility class has a isReachable
property which is true
if the device probably has a good connection, and false
if it probably does not.
Note: TLS errors are not network problems, so they would cause the isReachable
property to be true
.
How to use it
// first check that a network error occurred
if let networkError {
if NetworkReachability.shared.isReachable {
// report possible network connection problem
} else {
// it's probably not a network problem
}
}
First published 20 November 2022