Swift
SCNetworkReachability
iOS Development
Networking
Programming Tutorial

How to use SCNetworkReachability in Swift

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

SCNetworkReachability is a low-level Apple API for observing whether a route to a host or address appears reachable. It is useful for network-awareness features, but it does not prove that your server is healthy or that the internet is truly usable.

What the API Actually Tells You

The SystemConfiguration framework exposes SCNetworkReachability as a C-based API. In Swift, you usually wrap it in a small class so you can read flags and respond to changes more comfortably.

At a high level, the API answers questions such as:

  • is a route currently reachable
  • does a connection need to be established first
  • is the route currently using cellular on supported platforms

That is narrower than "the app can successfully call my backend." A captive portal, broken DNS, or server outage can still make requests fail even when reachability says a route is available.

Reading the Current Reachability Flags

The example below creates a reachability reference for a host and reads its current flags.

swift
1import Foundation
2import SystemConfiguration
3
4final class ReachabilityMonitor {
5    private let ref: SCNetworkReachability
6
7    init?(host: String) {
8        guard let ref = SCNetworkReachabilityCreateWithName(nil, host) else {
9            return nil
10        }
11        self.ref = ref
12    }
13
14    func currentFlags() -> SCNetworkReachabilityFlags? {
15        var flags = SCNetworkReachabilityFlags()
16        guard SCNetworkReachabilityGetFlags(ref, &flags) else {
17            return nil
18        }
19        return flags
20    }
21}
22
23let monitor = ReachabilityMonitor(host: "www.apple.com")
24if let flags = monitor?.currentFlags() {
25    let reachable = flags.contains(.reachable) && !flags.contains(.connectionRequired)
26    print("Reachable:", reachable)
27}

The common quick check is reachable && !connectionRequired. That gives a reasonable "probably usable" signal for many apps.

Listening for Reachability Changes

Polling flags occasionally works, but callbacks are usually better when the app needs to react to transitions.

swift
1import Foundation
2import SystemConfiguration
3
4final class ReachabilityMonitor {
5    private let ref: SCNetworkReachability
6    var onChange: ((SCNetworkReachabilityFlags) -> Void)?
7
8    init?(host: String) {
9        guard let ref = SCNetworkReachabilityCreateWithName(nil, host) else {
10            return nil
11        }
12        self.ref = ref
13    }
14
15    func start(on queue: DispatchQueue = .main) {
16        var context = SCNetworkReachabilityContext(
17            version: 0,
18            info: Unmanaged.passUnretained(self).toOpaque(),
19            retain: nil,
20            release: nil,
21            copyDescription: nil
22        )
23
24        let callback: SCNetworkReachabilityCallBack = { _, flags, info in
25            guard let info else { return }
26            let monitor = Unmanaged<ReachabilityMonitor>
27                .fromOpaque(info)
28                .takeUnretainedValue()
29            monitor.onChange?(flags)
30        }
31
32        SCNetworkReachabilitySetCallback(ref, callback, &context)
33        SCNetworkReachabilitySetDispatchQueue(ref, queue)
34    }
35
36    func stop() {
37        SCNetworkReachabilitySetDispatchQueue(ref, nil)
38    }
39}

Usage:

swift
1let monitor = ReachabilityMonitor(host: "www.apple.com")!
2monitor.onChange = { flags in
3    let reachable = flags.contains(.reachable) && !flags.contains(.connectionRequired)
4    print("Reachable changed:", reachable)
5}
6monitor.start()

Keep a strong reference to monitor. If it is deallocated, your callback logic disappears too.

Interpreting Flags Carefully

Reachability flags are hints, not a guarantee of successful traffic. For example, a route can be marked reachable while your actual API call still fails because the server is down or TLS negotiation breaks.

Also remember that isWWAN is a platform-specific flag and is primarily relevant on iOS. Do not build core network logic around that flag unless you have a concrete product reason.

When to Prefer NWPathMonitor

For newer Apple platforms, NWPathMonitor from the Network framework is often a friendlier API. It provides a higher-level view of path status and interface type. SCNetworkReachability still matters in legacy code and low-level integrations, but new applications often choose NWPathMonitor unless they specifically need the older API.

Common Pitfalls

The biggest pitfall is treating reachability as proof that the internet works. The only true proof is a real request to the service you care about.

Another issue is failing to retain the monitor object. If the wrapper is created in a local scope and then released, callbacks stop without much explanation.

Be careful to stop monitoring when appropriate. Leaving callbacks attached forever can complicate object lifecycle management.

Summary

  • 'SCNetworkReachability reports route reachability flags, not guaranteed end-to-end connectivity.'
  • In Swift, wrap the C API in a small class to read flags and handle callbacks safely.
  • A common reachability check is reachable && !connectionRequired.
  • Keep the monitor alive and detach it when you no longer need updates.
  • Consider NWPathMonitor for newer apps unless you specifically need SCNetworkReachability.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.