Should you use network connectivity checks in Swift?
Published on: May 16, 2025A lot of modern apps have a networking component to them. This could be because your app relies on a server entirely for all data, or you’re just sending a couple of requests as a back up or to kick off some server side processing. When implementing networking, it’s not uncommon for developers to check the network’s availability before making a network request.
The reasoning behind such a check is that we can inform the user that their request will fail before we even attempt to make the request.
Sound like good UX, right?
The question is whether it really is good UX. In this blog post I’d like to explore some of the pros and cons that a user might run into when you implement a network connectivity check with, for example, NWPathMonitor
.
A user’s connection can change at any time
Nothing is as susceptible to change as a user’s network connection. One moment they might be on WiFi, the next they’re in an elevator with no connection, and just moments later they’ll be on a fast 5G connection only to switch to a much slower connection when their train enters a huge tunnel.
If you’re preventing a user from initiating a network call when they momentarily don’t have a connection, that might seem extremely weird to them. By the time your alert shows up to tell them there’s no connection, they might have already restored connection. And by the time the actual network call gets made the elevator door close and … the network call still fails due to the user not being connected to the internet.
Due to changing conditions, it’s often recommended that apps attempt a network call, regardless of the user’s connection status. After all, the status can change at any time. So while you might be able to successfully kick off a network call, there’s no guarantee you’re able to finish the call.
A much better user experience is to just try the network call. If the call fails due to a lack of internet connection, URLSession will tell you about it, and you can inform the user accordingly.
Speaking of URLSession… there are several ways in which URLSession will help us handle offline usage of our app.
You might have a cached response
If your app is used frequently, and it displays relatively static data, it’s likely that your server will include cache headers where appropriate. This will allow URLSession to locally cache responses for certain requests which means that you don’t have to go to the server for those specific requests.
This means that, when configured correctly, URLSession can serve certain requests without an internet connection.
Of course, that means that the user must have visited a specific URL before, and the server must include the appropriate cache headers in its response but when that’s all set up correctly, URLSession will serve cached responses automatically without even letting you, the developer, know.
Your user might be offline and most of the app still works fine without any work from your end.
This will only work for requests where the user fetches data from the server so actions like submitting a comment or making a purchase in your app won’t work, but that’s no reason to start putting checks in place before sending a POST request.
As I mentioned in the previous section, the connection status can change at any time, and if URLSession wasn’t able to make the request it will inform you about it.
For situations where your user tries to initiate a request when there’s no active connection (yet) URLSession has another trick up its sleeve; automatic retries.
URLSession can retry network calls automatically upon reconnecting
Sometimes your user will initiate actions that will remain relevant for a little while. Or, in other words, the user will do something (like sending an email) where it’s completely fine if URLSession can’t make the request now and instead makes the request as soon as the user is back online.
To enable this behavior you must set the waitsForConnectivity
on your URLSession’s configuration to true
:
class APIClient {
let session: URLSession
init() {
let config = URLSessionConfiguration.default
config.waitsForConnectivity = true
self.session = URLSession(configuration: config)
}
func loadInformation() async throws -> Information {
let (data, response) = try await session.data(from: someURL)
// ...
}
In the code above, I’ve created my own URLSession instance that’s configured to wait for connectivity if we attempt to make a network call when there’s no network available. Whenever I make a request through this session while offline, the request will not fail immediately. Instead, it remains pending until a network connection is established.
By default, the wait time for connectivity is several days. You can change this to a more reasonable number like 60 seconds by setting timeoutIntervalForResource
:
init() {
let config = URLSessionConfiguration.default
config.waitsForConnectivity = true
config.timeoutIntervalForResource = 60
self.session = URLSession(configuration: config)
}
That way a request will remain pending for 60 seconds before giving up and failing with a network error.
If you want to have some logic in your app to detect when URLSession is waiting for connectivity, you can implement a URLSessionTaskDelegate
. The delegate’s urlSession(_:taskIsWaitingForConnectivity:)
method will be called whenever a task is unable to make a request immediately.
Note that waiting for connectivity won’t retry the request if the connection drops in the middle of a data transfer. This option only applies to waiting for a connection to start the request.
In summary
Handling offline scenarios should be a primary concern for mobile developers. A user’s connection status can change quickly, and frequently. Some developers will “preflight” their requests and check whether a connection is available before attempting to make a request in order to save a user’s time and resources.
The major downside of doing this is that having a connection right before making a request doesn’t mean the connection is there when the request actually starts, and it doesn’t mean the connection will be there for the entire duration of the request.
The recommended approach is to just go ahead and make the request and to handle offline scenarios if / when a network call fails.
URLSession has built-in mechanisms like a cache and the ability to wait for connections to provide data (if possible) when the user is offline, and it also has the built-in ability to take a request, wait for a connection to be available, and then start the request automatically.
The system does a pretty good job of helping us support and handle offline scenarios in our apps, which means that checking for connections with utilities like NWPathMonitor
usually ends up doing more harm than good.