iOS Networking
Build and review Apple-platform networking using URLSession with native async/await, structured concurrency, and Network.framework. Targets Swift 6.3 / iOS 26+.
Contents
Core Principles
- Prefer native async/await: Use
URLSession.shared.data(for:), download(for:), and bytes(for:) for all foreground network operations.
- Never swallow HTTP errors:
URLSession only throws for transport-level failures (offline, DNS, timeout). It does not throw on 4xx or 5xx responses. Always validate (200..<300).contains(httpResponse.statusCode).
- Keep retry policies bounded: Limit retries with exponential backoff and jitter. Only retry idempotent operations (GET, PUT, DELETE); never loop token refresh indefinitely.
- Isolate shared state: Isolate token storage, refresh locks, and cookie management inside actors or serial synchronization queues.
Status Code Validation and Error Contract
let (data, response) = try await session.data(for: request)
guard let httpResponse = response as? HTTPURLResponse else {
throw NetworkError.invalidResponse
}
guard (200..<300).contains(httpResponse.statusCode) else {
throw NetworkError.httpError(statusCode: httpResponse.statusCode, data: data)
}
Differentiate error categories: transport errors (URLError), decoding errors (DecodingError), client errors (4xx), server errors (5xx), and cancellation (CancellationError).
Foreground vs Background Transfers
| Transfer Mode |
API Pattern |
Session Configuration |
Suspension Behavior |
| Foreground Data |
try await session.data(for:) |
.default or .ephemeral |
Cancelled on app suspension |
| Foreground Download |
try await session.download(for:) |
.default |
Pauses/cancels on suspension |
| Background Transfer |
session.downloadTask(with:) with delegate |
URLSessionConfiguration.background(withIdentifier:) |
Managed out-of-process; relaunches app on finish |
| WebSocket |
session.webSocketTask(with:) |
.default |
Reconnection required on resume |
Route by Task
- For building reusable API clients, request encoders, authentication headers, and actors, read API Client and Request Building and Lightweight Clients.
- For resilient retries, certificate pinning, TLS security, and byte streaming, read Resilience, Security, and Streaming.
- For large file uploads, resume data, and progress tracking, read Uploads and Downloads and File Storage Patterns.
- For background transfers and app relaunch handlers, read Background Transfers. For real-time WebSockets, read WebSocket Networking.
- For cursor/offset pagination, AsyncSequence streams, and URLProtocol unit testing, read Pagination and URLProtocol Testing.
- For low-level TCP/UDP sockets, path monitoring, and cellular constraints with
NWPathMonitor, read Network Framework.
Common Mistakes
- Assuming
URLSession.data(for:) throws on HTTP 404 or 500 responses instead of inspecting statusCode.
- Using async/await convenience overloads on background
URLSessionConfiguration, which requires delegate callbacks.
- Retrying non-idempotent POST requests automatically after a network timeout.
- Leaking
NWPathMonitor instances or starting monitoring without setting a dispatch queue.
- Moving downloaded files after returning from
urlSession(_:downloadTask:didFinishDownloadingTo:) (file is deleted upon return).
Review Checklist
References
- API client and request building
- Lightweight clients
- Resilience, security, and streaming
- Uploads and downloads
- File storage patterns
- Background transfers
- WebSocket networking
- Pagination and URLProtocol testing
- Network.framework and NWPathMonitor
- URLSession documentation
- URLRequest documentation
1---2name: ios-networking3description: Builds or reviews Apple-platform networking with URLSession, async/await, and structured concurrency. Use for REST clients, uploads/downloads, WebSockets, pagination, retries, middleware, caching, background transfers, reachability, request errors, or network data loading.4---56# iOS Networking78Build and review Apple-platform networking using `URLSession` with native async/await, structured concurrency, and `Network.framework`. Targets Swift 6.3 / iOS 26+.910## Contents1112- [Core Principles](#core-principles)13- [Status Code Validation and Error Contract](#status-code-validation-and-error-contract)14- [Foreground vs Background Transfers](#foreground-vs-background-transfers)15- [Route by Task](#route-by-task)16- [Common Mistakes](#common-mistakes)17- [Review Checklist](#review-checklist)18- [References](#references)1920## Core Principles21221. **Prefer native async/await**: Use `URLSession.shared.data(for:)`, `download(for:)`, and `bytes(for:)` for all foreground network operations.232. **Never swallow HTTP errors**: `URLSession` only throws for transport-level failures (offline, DNS, timeout). It does **not** throw on 4xx or 5xx responses. Always validate `(200..<300).contains(httpResponse.statusCode)`.243. **Keep retry policies bounded**: Limit retries with exponential backoff and jitter. Only retry idempotent operations (GET, PUT, DELETE); never loop token refresh indefinitely.254. **Isolate shared state**: Isolate token storage, refresh locks, and cookie management inside actors or serial synchronization queues.2627## Status Code Validation and Error Contract2829```swift30let (data, response) = try await session.data(for: request)3132guard let httpResponse = response as? HTTPURLResponse else {33 throw NetworkError.invalidResponse34}3536guard (200..<300).contains(httpResponse.statusCode) else {37 throw NetworkError.httpError(statusCode: httpResponse.statusCode, data: data)38}39```4041Differentiate error categories: transport errors (`URLError`), decoding errors (`DecodingError`), client errors (4xx), server errors (5xx), and cancellation (`CancellationError`).4243## Foreground vs Background Transfers4445| Transfer Mode | API Pattern | Session Configuration | Suspension Behavior |46|---|---|---|---|47| Foreground Data | `try await session.data(for:)` | `.default` or `.ephemeral` | Cancelled on app suspension |48| Foreground Download | `try await session.download(for:)` | `.default` | Pauses/cancels on suspension |49| Background Transfer | `session.downloadTask(with:)` with delegate | `URLSessionConfiguration.background(withIdentifier:)` | Managed out-of-process; relaunches app on finish |50| WebSocket | `session.webSocketTask(with:)` | `.default` | Reconnection required on resume |5152## Route by Task5354- For building reusable API clients, request encoders, authentication headers, and actors, read [API Client and Request Building](references/api-client-and-request-building.md) and [Lightweight Clients](references/lightweight-clients.md).55- For resilient retries, certificate pinning, TLS security, and byte streaming, read [Resilience, Security, and Streaming](references/resilience-security-and-streaming.md).56- For large file uploads, resume data, and progress tracking, read [Uploads and Downloads](references/uploads-and-downloads.md) and [File Storage Patterns](references/file-storage-patterns.md).57- For background transfers and app relaunch handlers, read [Background Transfers](references/background-transfers.md). For real-time WebSockets, read [WebSocket Networking](references/websocket-networking.md).58- For cursor/offset pagination, AsyncSequence streams, and URLProtocol unit testing, read [Pagination and URLProtocol Testing](references/pagination-and-urlprotocol-testing.md).59- For low-level TCP/UDP sockets, path monitoring, and cellular constraints with `NWPathMonitor`, read [Network Framework](references/network-framework.md).6061## Common Mistakes6263- Assuming `URLSession.data(for:)` throws on HTTP 404 or 500 responses instead of inspecting `statusCode`.64- Using async/await convenience overloads on background `URLSessionConfiguration`, which requires delegate callbacks.65- Retrying non-idempotent POST requests automatically after a network timeout.66- Leaking `NWPathMonitor` instances or starting monitoring without setting a dispatch queue.67- Moving downloaded files after returning from `urlSession(_:downloadTask:didFinishDownloadingTo:)` (file is deleted upon return).6869## Review Checklist7071- [ ] HTTP status code explicitly validated before decoding payload72- [ ] Transport errors separated from server-returned error payloads73- [ ] Safe retry policy with jitter applied only to idempotent requests74- [ ] Auth token refresh uses actor isolation to avoid redundant refresh calls75- [ ] Background sessions configure delegate and move temporary files synchronously76- [ ] URLProtocol tests verify 2xx, 4xx, 5xx, timeout, and cancellation states77- [ ] App Transport Security (ATS) exceptions avoided unless strictly necessary7879## References8081- [API client and request building](references/api-client-and-request-building.md)82- [Lightweight clients](references/lightweight-clients.md)83- [Resilience, security, and streaming](references/resilience-security-and-streaming.md)84- [Uploads and downloads](references/uploads-and-downloads.md)85- [File storage patterns](references/file-storage-patterns.md)86- [Background transfers](references/background-transfers.md)87- [WebSocket networking](references/websocket-networking.md)88- [Pagination and URLProtocol testing](references/pagination-and-urlprotocol-testing.md)89- [Network.framework and NWPathMonitor](references/network-framework.md)90- [URLSession documentation](https://sosumi.ai/documentation/foundation/urlsession)91- [URLRequest documentation](https://sosumi.ai/documentation/foundation/urlrequest)