Skip to content
advanced Phase 15 · iOS Interview Preparation

iOS System Design

Design scalable iOS architectures: networking layers, caching, offline-first, and modular apps.

1h
4 problems
Topic Progress 0%

Networking Layer Design

API Client Architecture

Design a flexible networking layer with protocol-based abstraction. Define an Endpoint struct that encapsulates path, method, headers, body, and query items. Create an APIClient protocol with a generic request method that returns Decodable objects.

protocol APIClient {
    func request<T: Decodable>(_ endpoint: Endpoint) async throws -> T
}

Request and Response Handling

The NetworkService implements APIClient. Build URLRequest from Endpoint, execute with URLSession, and decode responses. Handle HTTP status codes with specific errors for unauthorized, not found, and server errors. Use JSONDecoder with date strategies for consistent parsing.

Retry and Error Recovery

Implement a RetryPolicy that determines whether to retry based on error type and attempt count. Retry on timeout and 5xx server errors. Use exponential backoff for retry delays. Add circuit breaker pattern to stop retrying after repeated failures.

Authentication

Handle token-based authentication with automatic refresh. Store tokens in Keychain. Intercept requests to add authorization headers. Refresh expired tokens transparently. Support multiple authentication methods through strategy pattern.

Caching Architecture

Multi-Layer Caching

Implement a caching hierarchy with memory cache (NSCache) for fast access, disk cache for persistence, and network as the final source. Each layer checks before fetching from the next layer.

class CacheManager {
    let memoryCache = NSCache<NSString, AnyObject>()
    let diskCache: DiskCache
    
    func get<T: Codable>(_ key: String, type: T.Type) async throws -> T {
        if let cached = memoryCache.object(forKey: key as NSString) as? T {
            return cached
        }
        if let diskData = try await diskCache.get(key) {
            let decoded = try JSONDecoder().decode(T.self, from: diskData)
            memoryCache.setObject(decoded as AnyObject, forKey: key as NSString)
            return decoded
        }
        throw CacheError.notFound
    }
}

Cache Invalidation

Use time-based expiration (TTL), event-based invalidation (user action), and version-based invalidation (API version changes). Tag cached entries for group invalidation when related data changes.

Image Caching

Use a dedicated image cache with downsampling. Cache images at display size, not original size. Implement memory pressure handling to evict images under pressure. Use URLCache for HTTP-level caching of image requests.

Offline-First Design

Data Synchronization

Store data locally with CoreData or SwiftData. Queue mutations when offline. Sync when connectivity returns. Handle conflicts with last-write-wins or merge strategies.

Sync Strategies

  • Optimistic sync: Apply changes locally immediately, sync in background
  • Pessimistic sync: Wait for server confirmation before applying locally
  • Conflict resolution: Use timestamps, version vectors, or operational transforms

Connectivity Monitoring

Use NWPathMonitor to track network state. Queue operations when offline. Retry failed syncs when connectivity returns. Show sync status to the user.

Modular Architecture

Split the app into feature modules with clear boundaries. Each module owns its data, networking, and UI. Use protocols for inter-module communication. Share common infrastructure through a core module.

Quiz

1. What is the benefit of a protocol-based networking layer?

Question 1 options

2. What is cache invalidation?

Question 2 options

3. What is optimistic sync?

Question 3 options

4. Why use modular architecture in large iOS apps?

Question 4 options

Flashcards

Question

What are the layers of a caching architecture?

Answer

Memory cache (NSCache for fast access), disk cache (persistence), and network (source of truth). Check each layer before fetching from the next.

Question

What is the difference between optimistic and pessimistic sync?

Answer

Optimistic applies changes locally immediately and syncs in background. Pessimistic waits for server confirmation before applying locally.

Question

What is the purpose of a circuit breaker in networking?

Answer

To stop retrying after repeated failures, preventing resource waste and allowing the server to recover.

Revision Notes

Key Takeaways

  • 1. Protocol-based networking enables testability and flexibility
  • 2. Multi-layer caching optimizes performance at every level
  • 3. Cache invalidation ensures data freshness
  • 4. Optimistic sync provides responsive user experience
  • 5. Modular architecture scales with team size

Interview Tips

  • Draw the architecture diagram before explaining details
  • Discuss trade-offs between different caching strategies
  • Explain how you handle offline scenarios and data conflicts
  • Walk through designing a networking layer for a social media app

Cheat Sheet

System Design Quick Reference

  • Protocol-based networking for testability
  • Multi-layer caching: memory, disk, network
  • Cache invalidation: TTL, event-based, version-based
  • Optimistic sync for responsive UI
  • Modular architecture for team independence
  • Circuit breaker for fault tolerance