Introduction
Alamofire provides NetworkReachabilityManager to monitor network connectivity changes in iOS apps. It reports whether the device can reach a host via WiFi, cellular, or not at all. However, reachability only checks if the network interface is available — it does not guarantee that a specific server is reachable or that the internet works.
Basic Reachability Check
1import Alamofire
2
3let reachabilityManager = NetworkReachabilityManager()
4
5reachabilityManager?.startListening(onUpdatePerforming: { status in
6 switch status {
7 case .notReachable:
8 print("No internet connection")
9 case .reachable(.ethernetOrWiFi):
10 print("Connected via WiFi")
11 case .reachable(.cellular):
12 print("Connected via Cellular")
13 case .unknown:
14 print("Network status unknown")
15 }
16})
Call stopListening() when you no longer need updates (e.g., in deinit):
deinit {
reachabilityManager?.stopListening()
}
Creating a Reachability Service
Wrap NetworkReachabilityManager in a singleton for app-wide access:
1import Alamofire
2
3class NetworkMonitor {
4 static let shared = NetworkMonitor()
5
6 private let reachabilityManager = NetworkReachabilityManager()
7 private(set) var isReachable = false
8 private(set) var isReachableViaWiFi = false
9 private(set) var isReachableViaCellular = false
10
11 private init() {}
12
13 func startMonitoring() {
14 reachabilityManager?.startListening(onUpdatePerforming: { [weak self] status in
15 guard let self = self else { return }
16
17 switch status {
18 case .notReachable:
19 self.isReachable = false
20 self.isReachableViaWiFi = false
21 self.isReachableViaCellular = false
22 case .reachable(.ethernetOrWiFi):
23 self.isReachable = true
24 self.isReachableViaWiFi = true
25 self.isReachableViaCellular = false
26 case .reachable(.cellular):
27 self.isReachable = true
28 self.isReachableViaWiFi = false
29 self.isReachableViaCellular = true
30 case .unknown:
31 self.isReachable = false
32 }
33
34 NotificationCenter.default.post(
35 name: .networkStatusChanged,
36 object: nil,
37 userInfo: ["isReachable": self.isReachable]
38 )
39 })
40 }
41
42 func stopMonitoring() {
43 reachabilityManager?.stopListening()
44 }
45}
46
47extension Notification.Name {
48 static let networkStatusChanged = Notification.Name("networkStatusChanged")
49}
Start monitoring in AppDelegate:
1func application(_ application: UIApplication,
2 didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
3 NetworkMonitor.shared.startMonitoring()
4 return true
5}
Checking Before Making a Request
1func fetchData() {
2 guard NetworkMonitor.shared.isReachable else {
3 showAlert(message: "No internet connection. Please check your network settings.")
4 return
5 }
6
7 AF.request("https://api.example.com/data")
8 .validate()
9 .responseDecodable(of: DataResponse.self) { response in
10 switch response.result {
11 case .success(let data):
12 self.updateUI(with: data)
13 case .failure(let error):
14 self.handleError(error)
15 }
16 }
17}
Monitoring for a Specific Host
Check reachability to a specific server instead of general internet:
1let manager = NetworkReachabilityManager(host: "api.example.com")
2
3manager?.startListening(onUpdatePerforming: { status in
4 switch status {
5 case .notReachable:
6 print("Cannot reach api.example.com")
7 case .reachable(_):
8 print("api.example.com is reachable")
9 case .unknown:
10 print("Unknown")
11 }
12})
Reacting to Network Changes in a ViewController
1class DataViewController: UIViewController {
2 private var networkObserver: NSObjectProtocol?
3
4 override func viewDidLoad() {
5 super.viewDidLoad()
6
7 networkObserver = NotificationCenter.default.addObserver(
8 forName: .networkStatusChanged,
9 object: nil,
10 queue: .main
11 ) { [weak self] notification in
12 guard let isReachable = notification.userInfo?["isReachable"] as? Bool else { return }
13
14 if isReachable {
15 self?.hideOfflineBanner()
16 self?.refreshData()
17 } else {
18 self?.showOfflineBanner()
19 }
20 }
21 }
22
23 deinit {
24 if let observer = networkObserver {
25 NotificationCenter.default.removeObserver(observer)
26 }
27 }
28
29 private func showOfflineBanner() {
30 // Show a banner indicating no connection
31 }
32
33 private func hideOfflineBanner() {
34 // Hide the offline banner
35 }
36}
Alternative: NWPathMonitor (No Alamofire)
Apple's Network framework provides NWPathMonitor as a built-in alternative:
1import Network
2
3let monitor = NWPathMonitor()
4
5monitor.pathUpdateHandler = { path in
6 if path.status == .satisfied {
7 print("Connected")
8 if path.usesInterfaceType(.wifi) {
9 print("Via WiFi")
10 } else if path.usesInterfaceType(.cellular) {
11 print("Via Cellular")
12 }
13 } else {
14 print("No connection")
15 }
16}
17
18monitor.start(queue: DispatchQueue.global())
| Feature | Alamofire NetworkReachabilityManager | NWPathMonitor |
| Dependency | Requires Alamofire | Built-in (iOS 12+) |
| Host-specific | Yes | No |
| Interface type | WiFi vs Cellular | WiFi, Cellular, Wired, Loopback |
| Constrained path | No | Yes (path.isConstrained) |
Common Pitfalls
Reachability is not connectivity: NetworkReachabilityManager checks if a network interface is available, not if the internet actually works. A device can be connected to WiFi but have no internet access (captive portal, DNS failure). For true connectivity checks, make a lightweight HTTP request.
Memory leaks: Always use [weak self] in the listener closure. Forgetting this creates a retain cycle between the manager and the view controller, preventing deallocation.
Main thread UI updates: The listener callback may fire on a background queue. Dispatch to the main queue before updating UI: DispatchQueue.main.async { ... }.
Simulator limitations: Network reachability on the iOS Simulator may not reflect the host Mac's actual network state accurately. Test on real devices.
Stop listening: Always call stopListening() when the monitor is no longer needed. In view controllers, do this in deinit. In singletons, call it when the app terminates.
Summary
Use NetworkReachabilityManager from Alamofire to monitor network status changes
Wrap it in a singleton (NetworkMonitor) for app-wide access
Check isReachable before making requests to provide immediate user feedback
Use NWPathMonitor as a built-in alternative if you do not want the Alamofire dependency
Reachability checks network interface availability, not actual internet connectivity — consider a lightweight ping for true connectivity verification