← All topics/Networking & data

Senior / Staff iOS — interview prep

Networking & data

URLSession · layers · errors · cache · pagination · offline

CodableURLCacheRetryIdempotencyCursorOutbox
01

Layer shape

Stack
i
Separate transport (how you call the network), endpoints (paths, method, headers), decoding, and domain errors — features depend on protocols, not raw URLSession everywhere.
PieceOwnsWhy
Client / sessionURLSession, auth adapters, logging, default timeouts.One place to tune behavior and swap fakes in tests.
EndpointsRoutes, query keys, body encoding — often enums or small structs.Prevents stringly-typed URLs scattered across features.
MapperJSON → models; HTTP status → typed app errors.UI and repositories see meaningful failures, not URLError soup.
02

Errors, retries & UX

Resilience
!
Retry transient failures (timeouts, connectivity) with backoff — not 4xx or broken contracts. Writes need idempotency or server-side dedup (request IDs) before blind replay.
Classify first
  • Map to app errors: unauthorized, not found, server, decoding, offline.
  • Log correlation IDs for support; avoid logging secrets or full tokens.
UX
  • Show cached data when possible; clear empty vs error vs offline.
  • Offer manual retry; don’t spin forever on background refresh.
Status + decode
let (data, response) = try await URLSession.shared.data(for: request)
guard let http = response as? HTTPURLResponse else {
  throw APIError.invalidResponse
}
switch http.statusCode {
case 200..<300: break
case 401: throw APIError.unauthorized
default: throw APIError.http(http.statusCode)
}
return try decoder.decode(T.self, from: data)
03

Caching

Layers
Where
  • Memory — hot images, session buffers; fast, evicted under pressure.
  • DiskURLCache, files; survives restart.
  • Database — queryable offline source of truth with staleness rules.
Policy
  • Per-resource TTL, etag / version headers, invalidate on logout.
  • Stale-while-revalidate for feeds: show cache, refresh in background.
URLCache + session
var config = URLSessionConfiguration.default
config.urlCache = URLCache(
  memoryCapacity: 50 * 1_024 * 1_024,
  diskCapacity: 200 * 1_024 * 1_024,
  directory: FileManager.default.urls(
    for: .cachesDirectory, in: .userDomainMask
  ).first
)
config.requestCachePolicy = .returnCacheDataElseLoad
let session = URLSession(configuration: config)
04

Pagination & feeds

Scale
Cursor / token

Prefer cursor or opaque next token for changing lists — avoids offset skips when rows shift. Client passes the marker back verbatim.

UI
  • Prefetch the next page before the user hits the end.
  • Dedupe loads; keep loading state per direction (head/tail).
  • Keep cell work light; image decode off the hot path.
05

Offline-first & sync

Writes
Local reads from DB/cache; writes enqueue to an outbox with stable client IDs — drain when online with retries and ordering per entity.
Conflicts
  • Pick strategy with product: last-write-wins, server wins, merge fields, or user resolve.
  • Use versions / etag / updatedAt to detect clashes.
APIs
  • Idempotent endpoints + request IDs so retries don’t double-charge.
  • Optimistic UI only when rollback is acceptable; else show pending.
Networking & data — interview prep cheat sheetAligned with practical question set