Back to all Roadmaps
SDE 3 & Team Lead

Mid-Level to Lead Roadmap

Explicit module boundaries, comprehensive testability, structured multi-threading management, and defending architectural designs under peer review. Covers MVVM, GCD, async/await, CoreData, and CI/CD pipelines.

Advanced Swift Language Features
Advanced Protocols & Types
Protocol with Associated Types (PAT)
Opaque Types (some)
Existential Types (any)
Primary Associated Types
Multiple Type Constraints
Generic where Clauses
Conditional Conformance
Retroactive Conformance
Property Wrappers & Macros
@Published
@AppStorage & @SceneStorage
Custom @propertyWrapper
@Observable Macro (iOS 17+)
@Model (SwiftData)
@resultBuilder DSLs
Attached & Freestanding Macros
Advanced Closures
[weak self] in closures
[unowned self] risks
Capture by value vs reference
Static Dispatch (struct, final)
V-Table Dispatch (class)
Message Dispatch (ObjC)
final keyword optimization
Memory Management & ARC
ARC Deep Dive
Retain Count Mechanics
Strong References (default)
weak var — auto-zeroing optional
unowned — assumes non-nil
Closure Retain Cycles
Delegate Retain Cycles
Timer & NotificationCenter Leaks
Memory Graph Debugger
Stack Allocation (value types)
Heap Allocation (reference types)
Copy-on-Write (CoW) mechanism
Leaks Instrument analysis
Allocations Instrument
Heap Shot analysis
Zombie Objects detection
Concurrency & Async Programming
Grand Central Dispatch
Main Queue (UI thread)
Global Queues (QoS)
Custom Serial / Concurrent Queues
sync vs async dispatch
DispatchGroup (notify / wait)
DispatchSemaphore
Barrier for Reader-Writer Lock
Deadlock prevention
async/await
Task { } & detached Task
Task.checkCancellation()
Task Priority (.userInitiated, .background)
TaskLocal values
withTaskGroup
withThrowingTaskGroup
async let (child tasks)
CheckedContinuation (bridging)
OperationQueue
Operation & BlockOperation
Operation Dependencies
Operation Cancellation
maxConcurrentOperationCount
AsyncStream
AsyncThrowingStream
for-await-in loop
compactMap / filter on AsyncSequence
Reactive Programming
Combine Framework
Publisher protocol
Subscriber protocol
PassthroughSubject
CurrentValueSubject
map / flatMap / compactMap
filter & removeDuplicates
debounce & throttle
combineLatest / zip / merge
.sink & .assign(to:)
Architecture Patterns
MVC & MVVM
MVC — Model / View / Controller
Massive ViewController problem
MVC improvements (child VCs, extensions)
MVVM — Model / View / ViewModel
Data Binding (Combine / @Observable)
ViewModel testability
No UIKit/SwiftUI in ViewModel
Advanced Architectures
MVP — Passive View & Presenter
VIPER — View/Interactor/Presenter/Entity/Router
Clean Architecture — Use Cases & Boundaries
TCA — The Composable Architecture
TCA — State, Action, Reducer
TCA — Effect & Environment
TCA — Scope & pullback
Dependency Injection & Design Patterns
Dependency Injection
Constructor / Initializer Injection
Property Injection
Method Injection
Protocol-based Abstractions
Singleton (correct use & pitfalls)
Factory & Abstract Factory
Coordinator Pattern
Observer (NotificationCenter, Combine)
Repository Pattern
Testing & Quality Assurance
XCTest & TDD
XCTestCase — setUp & tearDown
XCTAssert, XCTAssertEqual, XCTAssertNil
async/await test expectations
XCTest Performance measure {}
TDD — Red / Green / Refactor
Code Coverage in Xcode
Test Plans & Schemes
Test Doubles
Mocks — verify interactions
Stubs — return canned values
Fakes — working lightweight impl
Spies — record calls
XCUIApplication & launch
XCUIElement queries
accessibilityIdentifier usage
Snapshot Testing (SnapshotTesting lib)
Advanced Data Persistence
CoreData Stack
NSManagedObject & entities
NSFetchRequest & NSPredicate
NSManagedObjectContext threading
NSPersistentContainer
Background Context patterns
Batch Insert & Delete
Lightweight & Custom Migrations
NSFetchedResultsController
SwiftData @Model (iOS 17+)
ModelContext & ModelContainer
@Query macro with predicates
SwiftData Schema Migrations
Realm — Objects & write transactions
Realm change notifications
Keychain Services (intro)
SQLite & GRDB basics
CI/CD & Release Automation
Fastlane
match — code signing management
gym — build .ipa
deliver — App Store upload
scan — run tests
GitHub Actions for iOS
Workflows & Jobs (on: push/PR)
Matrix strategy for multi-sim
Dependency caching
Distribution Certificates
Provisioning Profiles
Entitlements & capabilities
TestFlight — internal & external
App Store Connect API
Firebase Crashlytics triage
Sentry crash monitoring
Team Leadership & Code Health
Constructive PR Reviews
SwiftLint — style enforcement
DocC — code documentation
Ticket breakdown & estimation
Crash log triage & symbolication
Hotfix branching strategy
Postmortems & blameless culture
Interview Preparation Guide
🧠 Interview Deep Dive

Preparation vs. Evaluation

Explicit module boundaries, comprehensive testability, structured multi-threading management, and defending architectural designs under peer review.

Mid-Level to Team Lead (SDE 3 & Team Lead)
What to Prepare
  • Queue Architecture — serial queues process one task at a time; concurrent queues process many; main queue is serial and must not be blocked
  • Sync dispatch to main queue from main queue = deadlock — the most common threading mistake in UIKit
  • async/await — eliminates callback pyramids, enforces structured lifetimes, integrates naturally with try/catch
  • Task Cancellation — Task.checkCancellation() must be called cooperatively; cancellation is not preemptive
  • Method Dispatch — final and private enable static dispatch (devirtualization), eliminating vtable overhead
What is Evaluated
  • Refactoring a completion-handler pyramid into async/await, demonstrating error-throwing compression
  • Identifying the data race in a code snippet where two queues write to a shared Array simultaneously
  • Explaining why DispatchQueue.main.sync from the main thread causes an immediate deadlock
What to Prepare
  • MVVM Clean Boundaries — ViewModel must have zero UIKit/SwiftUI imports; importing UI framework is an architectural failure
  • DI via Constructor Injection — inject protocol abstractions, never concrete types or shared singletons
  • Repository Pattern — conceals whether data comes from REST API, CoreData, or SQLite; single source of truth for presentation logic
  • Coordinator Pattern — removes navigation responsibility from ViewControllers; makes navigation testable and reusable
  • Protocol-based mocking — define a protocol for services so unit tests can inject fakes without touching real network/database
What is Evaluated
  • Analyzing a 1,500-line MassiveViewController and decomposing it into ViewModel, UseCases, and Repository layers on a whiteboard
  • Writing a URLProtocol subclass that intercepts network calls to simulate 404, 500, and timeout errors in unit tests
  • Defending MVVM vs TCA trade-offs for a new feature with complex state transitions
What to Prepare
  • TDD cycle — write a failing test (Red) → write minimal code to pass (Green) → improve code quality (Refactor)
  • Test Doubles — Mock (verifies interactions), Stub (returns canned data), Fake (real implementation, lightweight), Spy (records calls)
  • Async test patterns — use async throws test functions with await; avoid expectation + wait unless needed for Combine streams
  • Test isolation — each test should be independent; never share mutable state between test cases via class-level properties
  • Code coverage as a metric — aim for high coverage on business logic; UI tests cover critical user flows only
What is Evaluated
  • Writing a complete unit test for a ViewModel that fetches and transforms data, using a protocol-based mock network layer
  • Explaining why snapshot testing is valuable and what kinds of regressions it catches that unit tests miss
  • Setting up a test plan in Xcode with separate schemes for unit tests and UI tests
What to Prepare
  • CoreData threading — NSManagedObjectContext is not thread-safe; always use performAndWait on background contexts
  • NSFetchedResultsController — automatically drives UITableView/UICollectionView updates when CoreData entities change
  • SwiftData @Model macro (iOS 17+) — replaces NSManagedObject; ModelContext replaces NSManagedObjectContext
  • Migration strategy — lightweight migrations for adding optional attributes; custom policies for complex model changes
  • Keychain — use SecItemAdd for storing tokens; never UserDefaults for sensitive credentials
What is Evaluated
  • Whiteboarding a CoreData stack that handles background sync writes while serving a live-updating list to the UI
  • Explaining how to migrate a CoreData model when adding a required attribute to an entity with existing records
  • Designing a SwiftData schema with relationships and explaining how @Query predicates work

Click each topic to expand preparation details and interview evaluation criteria