iOS path · Doing the work · Topic 6 of 11

Networking with URLSession

Not started

URLSession is the system's HTTP client. You create a **session** from a configuration, and each request you make is a **task** in that session: a data task for ordinary requests, upload and download tasks for files, and WebSocket tasks. Since iOS 15 each kind also has an async method, so a request is one await.

Why it matters: Phones change networks, lose signal and get suspended mid-request. The session you choose decides what survives that.

  1. 1Session per purpose

    A session's configuration (timeouts, cache, cookies, cellular) applies to every task in it; make one per kind of traffic.

  2. 2HTTP caching is built in

    URLCache follows the server's cache headers by default, in memory and on disk.

  3. 3Background sessions outlive you

    Uploads and downloads in a background session run in a system process, even while your app is suspended.

1

How it works

The explanation, with examples you can run.

A session per kind of traffic

let api: URLSession = {    let config = URLSessionConfiguration.default    config.timeoutIntervalForRequest = 15    config.waitsForConnectivity = true          // wait for a network instead of failing at once    config.httpAdditionalHeaders = ["Accept": "application/json"]    return URLSession(configuration: config)}() func fetchOrders() async throws -> [Order] {    let (data, response) = try await api.data(from: Order.listURL)    guard let http = response as? HTTPURLResponse, (200..<300).contains(http.statusCode) else {        throw APIError.badStatus    }    return try JSONDecoder().decode([Order].self, from: data)}

URLSession.shared is fine for simple calls but can't be configured. Create your own sessions for anything else and keep them for the life of the app: each session owns a connection pool, and making one per request throws away connection reuse. The three configurations are default (disk cache, cookies, credentials), ephemeral (nothing written to disk) and background (below).

Two things that catch people out. A 404 or 500 is not an error to URLSession: you get a response and must check the status code yourself. And cancelling the Swift task that is awaiting data(from:) cancels the request, which is what you want when a SwiftUI .task is torn down.

All of this goes over HTTPS by default: App Transport Security blocks plain HTTP and weak TLS unless you add exceptions in Info.plist.

Caching you get for free

Responses are stored in URLCache (memory and disk) and reused according to the server's Cache-Control, ETag and Last-Modified headers; that is what the default policy, useProtocolCachePolicy, means. You can override it per request, for example .returnCacheDataElseLoad to show something offline. Apple's docs point out that the default policy also writes HTTPS responses to disk, which you may not want for personal data; use an ephemeral session or veto caching in the session delegate.

Transfers that survive suspension

A normal session stops when your app is suspended. For uploads and downloads that must finish anyway, use a background session: the transfer is done by a system process, which can wait for Wi-Fi or power when you set isDiscretionary.

let config = URLSessionConfiguration.background(withIdentifier: "com.example.sync")config.sessionSendsLaunchEvents = truelet session = URLSession(configuration: config, delegate: syncDelegate, delegateQueue: nil)session.downloadTask(with: exportURL).resume()

Background sessions only support upload and download tasks, report through a delegate rather than async returns, and wake the app when they finish: the app delegate receives application(_:handleEventsForBackgroundURLSession:completionHandler:), you recreate the session with the same identifier, handle the delegate events, then call the completion handler. If the user force-quits the app, its background transfers are cancelled.

For retries, remember the phone's network is the least reliable part of the system: retry idempotent requests with backoff and jitter, and send an idempotency key with the rest.

2

Check yourself

3 questions. Get them all right to finish this topic.

  1. 1.What is special about a session created with URLSessionConfiguration.background(withIdentifier:)?
  2. 2.The user force-quits your app from the app switcher during a background download. What happens?
  3. 3.Which session configuration keeps no caches, cookies or credentials on disk?

0 of 3 right so far. Get all three to finish this topic.