Reachability is a library for iOS and macOS built on the SystemConfiguration framework that allows checking internet connection availability and tracking its changes. According to Apple Developer Documentation (2025), Reachability uses SCNetworkReachability for asynchronous network monitoring. The Reachability library remained the standard for iOS projects for a long time until the native NWPathMonitor appeared.
Key Takeaways
Reachability is a sample library from Apple demonstrating the use of the SystemConfiguration framework for network monitoring. The source code was published in Apple Developer Documentation as an example, but the community adopted it as the standard tool for checking connectivity in iOS projects.
The library is based on SCNetworkReachability — a C-function from SystemConfiguration that evaluates the reachability of a remote host or IP address. When creating Reachability, you specify either a hostname (e.g., google.com) or an IP address, and the library asynchronously checks whether this host is reachable through the device’s current network interfaces.
Reachability’s popularity stems from its simplicity: just create an instance, subscribe to notifications via NotificationCenter, and listen for kReachabilityChangedNotification. In response, the app receives a status: NotReachable, ReachableViaWiFi, or ReachableViaWWAN (cellular data).
Reachability first appeared in iPhone OS 2 (2008) along with the SystemConfiguration framework. For a decade it was the only native way to monitor network status in iOS. With the release of iOS 12 and the Network framework, Apple recommends NWPathMonitor as a replacement, but Reachability is still supported.
Many third-party wrappers — AFNetworking, Alamofire, AshleyDodd/Reachability.swift — use the underlying SCNetworkReachability mechanism. These libraries add a convenient Swift/Objective-C interface, status memoization, and thread-safe callbacks while maintaining the same SystemConfiguration foundation.
The main mechanism of Reachability is the SCNetworkReachabilityCreateWithName function, which creates a tracking object for the specified host. Then SCNetworkReachabilityGetFlags is called — a synchronous check that returns a bitmask of SCNetworkReachabilityFlags with the current network state.
For asynchronous monitoring, SCNetworkReachabilitySetCallback is used, registering a C callback function. The callback runs on the current RunLoop when the host reachability state changes. Reachability wraps this C-callback into an Objective-C method and sends a Notification through NotificationCenter.
import SystemConfiguration
class Reachability {
private var reachabilityRef: SCNetworkReachability?
init?(hostname: String) {
reachabilityRef = SCNetworkReachabilityCreateWithName(
nil, hostname
)
}
func checkReachability() -> Bool {
var flags = SCNetworkReachabilityFlags()
SCNetworkReachabilityGetFlags(
reachabilityRef!, &flags
)
return isReachable(with: flags)
}
private func isReachable(with flags: SCNetworkReachabilityFlags) -> Bool {
let reachable = flags.contains(.reachable)
let connectionRequired = flags.contains(.connectionRequired)
return reachable && !connectionRequired
}
}
SCNetworkReachabilityFlags is a bitmask that encodes the network state. The kSCNetworkReachabilityFlagsReachable flag indicates that the host is reachable. kSCNetworkReachabilityFlagsConnectionRequired — a connection needs to be established. The combination of flags determines whether the application can send data.
Additional flags: kSCNetworkReachabilityFlagsIsWWAN — connection via cellular network (iOS), kSCNetworkReachabilityFlagsInterventionRequired — user intervention required (e.g., for VPN). Reachability considers these flags to determine the interface type.
The standard pattern for using Reachability in an iOS app includes creating an instance, subscribing to notifications, and reacting to status changes. The example below shows integration with NotificationCenter to update the UI when the network changes.
import Reachability
import UIKit
class ViewController: UIViewController {
var reachability: Reachability?
override func viewDidLoad() {
super.viewDidLoad()
reachability = Reachability(hostname: "google.com")
NotificationCenter.default.addObserver(
self,
selector: #selector(reachabilityChanged),
name: .reachabilityChanged,
object: nil
)
reachability?.startNotifier()
}
@objc func reachabilityChanged(notification: Notification) {
if let reachability = notification.object as? Reachability {
switch reachability.connection {
case .wifi:
print("Connected via Wi-Fi")
case .cellular:
print("Connected via cellular")
case .unavailable:
print("No connection")
}
}
}
}
Before making an HTTP request, you can check network availability synchronously: reachability.connection != .unavailable. This does not guarantee request success (the server may be unavailable), but prevents obviously failing requests and improves UX — the app does not show a spinner in offline mode.
For more accurate checking, combine Reachability with URLSession timeouts. If Reachability shows reachable but the request fails within the timeout — there is likely a server-side issue or a captive portal. In such cases, you can show the user a server unreachable message.
Reachability distinguishes three main connection states: Wi-Fi, cellular data (WWAN), and unreachable. WWAN includes all cellular connection types — 2G, 3G, 4G/LTE, 5G. The library does not provide granularity within WWAN, so distinguishing 4G from 5G requires CoreTelephony.
| State | SCNetwork Flag | Description |
|---|---|---|
| ReachableViaWiFi | Reachable + !IsWWAN | Connected via Wi-Fi network with host access |
| ReachableViaWWAN | Reachable + IsWWAN | Connected via cellular network (2G-5G) |
| NotReachable | !Reachable | Host is unreachable through any interface |
| ConnectionRequired | Reachable + ConnectionRequired | Connection establishment required (VPN, PPPoE) |
Reachability does not distinguish Ethernet, VPN tunnels, or multipath connections — all non-WWAN interfaces are classified as Wi-Fi. This limitation stems from the SystemConfiguration architecture, which does not provide detailed information about network interfaces beyond basic classification.
For determining the specific cellular connection type (4G vs 5G), CTTelephonyNetworkInfo from CoreTelephony is required. Combining Reachability with CoreTelephony allows the app to select content quality: on 5G — stream in 4K, on 4G/LTE — HD, on 3G — SD or audio only.
Apple recommends replacing Reachability with NWPathMonitor in all new projects starting from iOS 12. The main reason is that NWPathMonitor is part of the modern Network framework, written in Swift, supports Combine, and provides detailed network path information without using C-compatibility.
The migration process includes replacing SCNetworkReachability with NWPathMonitor, switching from NotificationCenter to a pathUpdateHandler closure or Combine publisher. The algorithm and logic for handling network status remain the same — only the monitoring API changes.
protocol NetworkMonitorProtocol {
var isReachable: Bool { get }
var connectionType: ConnectionType { get }
func startMonitoring()
func stopMonitoring()
}
enum ConnectionType {
case wifi, cellular, ethernet, unavailable
}
// Modern implementation using NWPathMonitor
class ModernNetworkMonitor: NetworkMonitorProtocol {
private let monitor = NWPathMonitor()
private let queue = DispatchQueue("Network")
private var currentPath: NWPath?
var isReachable: Bool {
currentPath?.status == .satisfied
}
func startMonitoring() {
monitor.pathUpdateHandler = { [weak self] path in
self?.currentPath = path
}
monitor.start(on: queue)
}
func stopMonitoring() {
monitor.cancel()
}
}
For projects targeting iOS 12+, replace Reachability with NWPathMonitor entirely. For projects supporting iOS 11, use conditional compilation #available(iOS 12, *) with NWPathMonitor and Reachability as a fallback. This allows gradual migration without losing support for older devices.
The main advantage of migration is network path granularity. NWPathMonitor reports not just “reachable/unreachable” but also each interface type, their costs, priority, proxy and VPN support. This gives the developer more data to adapt application behavior to current network conditions.
Frequently Asked Questions
Reachability based on SCNetworkReachability is available starting from iPhone OS 2 (iOS 2). The library works on all iOS versions, including current ones. Limitations are not about the OS version but about information granularity — older versions do not distinguish between 4G and 5G.
Reachability uses SCNetworkReachability — a system service that evaluates host reachability at the network stack level without sending packets. Ping sends ICMP packets and consumes traffic, and can also be blocked by a firewall. Reachability is faster and safer for frequent checking.
Yes, Reachability works in SwiftUI through ObservableObject or Combine. Wrap it in a class subscribed to NotificationCenter and publish the status via @Published. For new SwiftUI projects, we recommend NWPathMonitor with a Combine publisher for reactive View updates.
Reachability checks the kSCNetworkReachabilityFlagsIsWWAN flag in the SCNetworkReachabilityFlags bitmask. If the flag is set — the connection is via cellular (WWAN), if not and the host is Reachable — via Wi-Fi. This is the only way to distinguish types without CoreTelephony.
SCNetworkReachability checks host reachability at the network layer but does not guarantee higher-level protocol operation. Possible causes: captive portal, DNS blocking, proxy server, or firewall. Reachability is the first filter but not a replacement for an actual HTTP request.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also