When do you still need a URLSession delegate, and how do the async APIs and per-task delegates fit?
Mental model. The async call is ordering takeaway: you get the food. The delegate is standing in the kitchen: you are told about every event (a missing ingredient, a delay), and can make decisions along the way.
The async methods (data(for:), download, upload, bytes) cover most calls with no delegate. You still need one, at session or task level, for things that are events rather than results: authentication and trust challenges (urlSession(_:didReceive:completionHandler:) for client certificates, basic auth and server-trust evaluation such as pinning, Q317), redirect control (willPerformHTTPRedirection, to refuse or modify a redirect, for example to avoid forwarding credentials), progress (didSendBodyData, didWriteData), metrics (didFinishCollecting), caching decisions (willCacheResponse), background sessions (always) and tasks that must wait for connectivity events (taskIsWaitingForConnectivity).
Two ways to attach one. A session delegate is passed when you create the URLSession and sees every task; the session retains its delegate until invalidated (finishTasksAndInvalidate), which is a classic leak: a session created per screen with self as the delegate keeps the screen alive. A per-task delegate (the delegate: parameter of the async methods) applies to that one task and is retained only for its lifetime, so it is the neat choice for “show progress for this download” and “handle this one auth challenge”. Delegate callbacks arrive on the session’s delegate queue (a serial operation queue), so hop to the right actor before touching state, and always call the completion handler exactly once. Use one shared session per configuration (do not create a session per request: you lose connection reuse).
Common traps
- Creating a session per screen with
selfas delegate and never invalidating it. The session retains the delegate. - Creating a new
URLSessionfor every request. It defeats connection reuse and wastes memory.
They might follow up with
- Which delegate method handles pinning? The server-trust challenge in
didReceive challenge; evaluate the trust and call the completion handler once. - Where do progress updates come from with async? A per-task delegate, or
task.progress(key-value observation) from a separateURLSessionTask.
Related questions
- 12.10.1 When do you use Network.framework (NWConnection, NWListener, NWPathMonitor) instead of URLSession, and how…
- 6.5.4 How does a background URLSession keep working when the app is not running?
- 12.1.1 What do the URLSession configurations control, and how do default, ephemeral and background sessions differ?
- 12.2.2 How do TLS and App Transport Security protect a request, and what is certificate pinning, and why is it…
- 12.4.2 How do you do multipart uploads, large uploads and downloads, and show progress?
← When do you use Network.framework (NWConnection, NWListener… A request fails or is slow only for some users. How do you diagnose… →