Swift
Internet Connection
Programming
Networking
iOS Development

Check for internet connection with 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

Checking for an internet connection in Swift sounds simple, but there are really two different questions. One is whether the device currently has a usable network path. The other is whether your actual backend or website is reachable. NWPathMonitor answers the first question well; a real request answers the second.

Use NWPathMonitor for Reachability State

Apple's modern reachability tool is NWPathMonitor from the Network framework. It tells you whether the system currently sees a satisfied path and whether that path uses Wi-Fi, cellular, or another interface.

swift
1import Foundation
2import Network
3
4final class ConnectivityMonitor {
5    private let monitor = NWPathMonitor()
6    private let queue = DispatchQueue(label: "ConnectivityMonitor")
7
8    private(set) var isConnected = false
9
10    func start() {
11        monitor.pathUpdateHandler = { [weak self] path in
12            self?.isConnected = path.status == .satisfied
13            print("Connected: \(path.status == .satisfied)")
14            print("Using Wi-Fi: \(path.usesInterfaceType(.wifi))")
15            print("Using Cellular: \(path.usesInterfaceType(.cellular))")
16        }
17        monitor.start(queue: queue)
18    }
19
20    func stop() {
21        monitor.cancel()
22    }
23}

That is the right building block for updating UI state, disabling network-dependent actions, or explaining to the user that the device currently has no route to the network.

Reachability Is Not the Same as Real Internet Access

A satisfied path does not guarantee your app can talk to the service it needs. The device may be on a captive portal, a misconfigured Wi-Fi network, or a filtered corporate network.

If your real question is "can I reach my API right now," make a small request to a health endpoint:

swift
1import Foundation
2
3func probeBackend() async -> Bool {
4    guard let url = URL(string: "https://example.com/health") else {
5        return false
6    }
7
8    var request = URLRequest(url: url)
9    request.httpMethod = "GET"
10    request.timeoutInterval = 5
11
12    do {
13        let (_, response) = try await URLSession.shared.data(for: request)
14        guard let httpResponse = response as? HTTPURLResponse else {
15            return false
16        }
17        return (200...299).contains(httpResponse.statusCode)
18    } catch {
19        return false
20    }
21}

That second check is what proves your service is reachable, not just that some network path exists.

A Good App Usually Uses Both

In practice, many apps combine both techniques:

  • 'NWPathMonitor updates general connectivity state'
  • a real request confirms service availability when needed

That separation keeps the app honest. It prevents you from showing a misleading "online" badge when the device has a path but your backend is down.

Avoid the Old Synchronous Habit

Older iOS code often tried to do a one-off synchronous reachability check before every request. That pattern leads to brittle logic. A better approach is:

  • observe path changes continuously
  • keep networking code resilient to request failures
  • handle real request errors even when reachability says a path exists

The network can always change between the check and the request anyway, so the request path still needs proper error handling.

Common Pitfalls

  • Treating NWPathMonitor as proof that your API is reachable.
  • Running a one-time connectivity check and assuming it stays valid.
  • Forgetting to keep a strong reference to the monitor so it continues running.
  • Updating UI directly from the monitor's background queue instead of dispatching to the main queue when needed.
  • Building logic that skips real error handling because a reachability check passed earlier.

Summary

  • Use NWPathMonitor to learn whether the device currently has a usable network path.
  • Use a real URLSession request to confirm that your backend is reachable.
  • Reachability and service availability are related but different checks.
  • Keep the monitor alive and handle updates on the correct queue.
  • Even with reachability monitoring, actual requests still need robust error handling.

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.