Production-grade networking & API integration patterns for iOS and macOS. Use when designing, implementing, debugging, or reviewing app networking: URLSession async/await, authentication (OAuth2/JWT), error handling, retries, caching (ETag/URLCache), REST & GraphQL, WebSockets, network monitoring, offline queues, and example code + scripts to accelerate delivery.
Purpose: Equip Claude with a complete, opinionated, battle-tested approach to building robust networking layers for iOS/macOS apps, with copy‑pasteable Swift, production‑ready Python utilities, and thorough guidance.
This Skill packages a pragmatic architecture for client networking that:
URLSession with Swift Concurrency (async/await).URLCache.Network.framework and adapts (e.g., waitsForConnectivity).Folder Structure
apple-networking-apis/
├── SKILL.md
├── scripts/
│ ├── generate_api_client.py
│ ├── mock_server.py
│ ├── network_interceptor.py
│ └── auth_manager_generator.py
├── swift/
│ ├── APIClientAsyncAwait.swift
│ ├── AuthManagerTokenRefresh.swift
│ ├── NetworkError.swift
│ ├── RetryWithBackoff.swift
│ ├── LoggingURLProtocol.swift
│ ├── MultipartUpload.swift
│ ├── WebSocketClient.swift
│ ├── NetworkMonitor.swift
│ └── OfflineQueue.swift
├── docs/
│ ├── authentication-flows.md
│ ├── error-handling-patterns.md
│ └── caching-strategies.md
└── examples/
├── mock-server-config.json
├── requests.http
└── graphql/query.graphql
URLSession and networking standards evolve with each iOS and macOS release. In rapidly changing ecosystems you must verify your assumptions before implementing code. This skill includes a snapshot of best practices as of 28 Oct 2025; use the guidelines below to keep your networking stack up to date.
web_search("URLSession iOS [version] new features") to identify new capabilities or deprecations.web_search("App Transport Security iOS [version] requirements").web_search("HTTP/3 iOS [version] support") or web_search("WebSocket iOS [version] native support").web_search("Apollo iOS Swift 6 concurrency support [version]").Trigger a search whenever you encounter:
request.assumesHTTP3Capable = false to disable HTTP/3 in tests【325481821916823†L20-L56】).Last verified: 2025‑10‑28 (covering iOS 17–18)
Update frequency: Quarterly (review after each major OS release)
Use this Skill when:
Skip this Skill when:
Layered Design
URLSession (data, upload, download) with request building, decoding, and cancellation.AuthManager that supplies/refreshes tokens and injects headers; isolates Keychain, PKCE, and provider‑specific quirks.UserAPI, PaymentsAPI) built on Transport; model decoding is local to each.NWPathMonitor + waitsForConnectivity for graceful connectivity recovery.Concurrency Principles
async/await over callbacks or Combine for clarity.actors when they hold mutable state (e.g., token refresh coalescing).withTaskCancellationHandler for cleanup (e.g., cancel WebSocket pings).HTTP Semantics
Configuration:
URLSessionConfiguration.default for general API calls..ephemeral for privacy‑sensitive flows (no persistent cookies/cache)..background(withIdentifier:) for long‑running uploads/downloads.waitsForConnectivity = true to avoid failing immediately on brief outages.multipathServiceType = .handover for seamless Wi‑Fi/Cell transitions (entitlement required).timeoutIntervalForRequest and timeoutIntervalForResource distinctly.configuration.allowsConstrainedNetworkAccess to false for sessions (or URLRequest.allowsConstrainedNetworkAccess for individual requests). If a request fails because the network is constrained, inspect the error’s networkUnavailableReason for .constrained and fall back to lower‑resolution or delayed resources【313413104212836†L24-L64】【313413104212836†L144-L147】.Request Building:
Encodable for bodies and URLQueryItem for queries.Decoding:
JSONDecoder with ISO‑8601 or server‑specific date strategy.application/problem+json error envelopes (RFC 7807).Cancellation:
CancellationError as a non‑fatal path.deinit or onDisappear.withCheckedThrowingContinuation carefully (avoid retaining self).async functions to be cancellation‑friendly; check Task.isCancelled before heavy work.TaskGroup for fan‑out/fan‑in where appropriate; cap concurrency.Task {} from within async API code unless intentionally detaching work.actor isolation for token refresh and offline queue mutation.Authorization Code + PKCE (OAuth 2.1, recommended):
Use the authorization code flow with Proof Key for Code Exchange (PKCE). OAuth 2.1 removes the implicit grant flow and mandates PKCE for all public clients【964654021945925†L61-L80】.
Launch with ASWebAuthenticationSession, specifying a custom scheme or Universal Link. Enforce exact redirect URI matching and specify required scopes (e.g., openid profile offline_access).
Exchange the code for tokens at the token endpoint; store access and refresh tokens securely in the Keychain and never persist them in UserDefaults or plain files【544542894411502†L112-L140】.
Use short‑lived access tokens (5–15 minutes) and rotate refresh tokens on every use【544542894411502†L168-L174】【964654021945925†L139-L179】. Implement single‑flight refresh logic to avoid token storms.
Client Credentials (device‑to‑service):
JWT / Custom:
Use signed JWTs for service authentication. Choose strong signing algorithms (RS256 or ES256), keep the payload minimal, and validate signature, expiration, issuer and audience on every request【544542894411502†L112-L140】.
Store JWTs securely in the Keychain; avoid localStorage or sessionStorage and always use HTTPS because JWTs are bearer tokens【544542894411502†L152-L160】.
Rotate signing keys regularly and use short expirations. Pair JWTs with refresh tokens when appropriate and rotate refresh tokens on each exchange【544542894411502†L168-L174】.
Keychain:
kSecClassGenericPassword, scoped via access groups when sharing across apps or extensions.errSecDuplicateItem by updating; always set kSecAttrAccessible appropriately.Edge Cases:
expires_in, but proactively refresh within a safety window (e.g., 60–120s).actor to avoid token races.Define a typed NetworkError that captures:
URLError family (DNS, timeouts, TLS).Log with a request ID and redact sensitive fields (Authorization, Set‑Cookie, tokens, PII).
Retry-After.sleep = random(0, base * 2^attempt).Cache-Control, ETag, Last-Modified). Prefer ETag revalidation with If-None-Match.URLCache with tuned memory/disk sizes; set useProtocolCachePolicy unless the server is misconfigured.Encodable request models and Decodable responses; keep DTOs separate from domain models if mapping is non‑trivial.If-Match when needed.Use Apollo iOS (SPM) for codegen, normalized caching, and typed operations.
Co‑locate .graphql operations with feature code; generate during build via script.
Enable persisted queries and automatic persisted queries (APQ) when available.
Treat GraphQL errors distinctly: transport OK with errors array is still a failure at the application layer.
Cache normalized entities; prefer fine‑grained cache invalidation over manual busting.
Upgrade to Apollo iOS 2.0 when possible – the 2025 major release embraces Swift 6 structured concurrency, making query execution async/await friendly. All generated types conform to Sendable and tasks compose elegantly. Deployment targets are raised to iOS 15/macOS 12 and CocoaPods support is dropped【885399316124246†L244-L275】【885399316124246†L283-L288】.
HTTP/3 uses the QUIC transport to provide native multiplexing and eliminate head‑of‑line blocking. Safari and URLSession added experimental HTTP/3 support with Safari 14 (iOS 14/macOS 11) and enabled it by default in Safari 16.4 for all users starting in September 2024【468735740034669†L392-L400】. When targeting iOS 17/18, HTTP/3 is typically available, but some simulators (for example the iOS 18.4 simulator) have bugs that break duplicate requests; disable HTTP/3 for simulator builds by setting request.assumesHTTP3Capable = false【325481821916823†L20-L56】. Always let URLSession negotiate the protocol – it will automatically fall back to HTTP/2 or HTTP/1.1 when servers do not advertise HTTP/3 support. Monitor task.metrics.protocolName to observe negotiated versions and log anomalies. Before enabling HTTP/3 on your server, confirm your CDN, load balancer and TLS termination support QUIC and use strong cipher suites.
SSE delivers unidirectional, real‑time updates over a persistent HTTP connection. Although iOS lacks a first‑party SSE client, you can implement one by initiating a long‑lived URLSession.dataTask and parsing lines that start with data:. Ensure you handle reconnects with exponential backoff, send a Last-Event-ID header to resume from the last event, and switch to WebSockets when you need bi‑directional communication. Monitor network reachability and respect Low Data Mode by deferring high‑frequency events.
URLSessionWebSocketTask provides first‑class WebSocket support on Apple platforms. It handles both text and binary messages, includes built‑in ping/pong, supports secure wss:// connections, and lets you gracefully close connections【495094527833113†L80-L90】. For advanced use cases (custom protocols, high‑performance or peer‑to‑peer streams), use NWConnection from Network.framework (iOS 14+) to create WebSocket connections. NWConnection offers granular state management, custom protocol stacks, seamless network interface switching and improved performance【495094527833113†L144-L159】, and sample code demonstrates how to establish and handle connection states【495094527833113†L162-L182】. Wrap your send and receive loops with Swift concurrency (for await) and incorporate periodic pings and reconnect logic as shown in WebSocketClient.swift.
Use grpc‑swift for efficient, strongly‑typed remote procedure calls. gRPC Swift 2 (released Feb 14 2025) introduces first‑class concurrency with async/await, Protocol Buffers code generation, pluggable transports (HTTP/2), smart client features such as client‑side load balancing and retries, and a flexible interceptor layer for authentication, logging and metrics【329925304272063†L20-L63】. When adopting gRPC, ensure your deployment target meets the minimum requirement (typically iOS 15+) and validate that your API gateway and load balancer support HTTP/2 and streaming. Use interceptors to inject OAuth tokens or custom metadata and to implement metrics and tracing.
URLSessionConfiguration.allowsConstrainedNetworkAccess and URLRequest.allowsConstrainedNetworkAccess to false. When a request fails because the network is constrained, inspect error.networkUnavailableReason == .constrained and fall back to lower‑quality assets【313413104212836†L24-L64】【313413104212836†L144-L147】.URLSessionWebSocketTask:
for await style or callback loop.NWPathMonitor to expose reachability, expensive path detection (cellular), and interface type.waitsForConnectivity for temporary outages; show lightweight UI affordances (“Connecting…”).satisfied; respect ordering and backoff.CancellationError and showing spinners forever.NSURLErrorNotConnectedToInternet: ensure waitsForConnectivity or present offline UI; consider NWPathMonitor to avoid futile calls.If-None-Match is set and server emits strong or weak ETag consistently.closeCode and reasons.URLProtocol logger with header/body redaction and OSLog integration.AuthManager for OAuth2/JWT with refresh, PKCE (optional), and Keychain storage.Key examples you can copy‑paste into your project:
APIClientAsyncAwait.swift — generic send/decode + typed endpoint.AuthManagerTokenRefresh.swift — actor‑based token manager with single‑flight refresh.NetworkError.swift — unified error type and mapping.RetryWithBackoff.swift — generic retry helper with exponential backoff + jitter.LoggingURLProtocol.swift — request/response interceptor & redaction.MultipartUpload.swift — multipart/form‑data builder & upload.WebSocketClient.swift — robust WebSocket client (pings, reconnect).NetworkMonitor.swift — NWPathMonitor wrapper.OfflineQueue.swift — durable offline request queue.This Skill is intentionally opinionated to minimize bikeshedding and maximize delivery speed. Adapt policies (timeouts, retry limits, logging) to your product and regulatory context. Integrate incrementally—start with Transport + Error types, then add Auth, Retry, and Caching. Build observability early to shorten MTTR.