Skip to content

christopherkmoore/iOS-Practice

Repository files navigation

iOS Interview Practice Projects

Four Xcode projects designed for senior iOS interview preparation, covering concurrency patterns, SwiftUI development, unit testing, and advanced Swift concurrency.

Requirements: Xcode 15+, iOS 17+


Quick Start

git clone https://github.com/christopherkmoore/iOS-Practice.git
cd iOS-Practice

Each project includes a pre-generated .xcodeproj. Open any project directly:

open ConcurrencyBugHunt/ConcurrencyBugHunt.xcodeproj
open SwiftUIBuilder/SwiftUIBuilder.xcodeproj
open TestabilityWorkshop/TestabilityWorkshop.xcodeproj
open ConcurrencyWorkshop/ConcurrencyWorkshop.xcodeproj

Using xcodegen? Each project also includes a project.yml for regeneration:

cd ConcurrencyBugHunt && xcodegen generate

Projects Overview

1. ConcurrencyBugHunt

Purpose: Code review practice — identify and fix concurrency bugs

How to use:

  • Run the app and navigate to each exercise
  • Each view contains intentionally buggy code
  • Read the code, identify the bug(s), then verify by running
  • Try to fix each bug before looking at solutions
Section Exercises Key Bugs
GCD Issues Race Condition Unsynchronized shared mutable state
Main Thread Violation UI updates from background thread
Deadlock Sync dispatch to current queue, lock ordering
Async/Await Task Cancellation Missing cancellation checks, stale results
Actor Reentrancy State changes during await suspension
Unstructured Task Leak Tasks outliving views, missing cleanup
Combine Publisher Retain Cycle Strong self in sink closures
Missing Cancellable Subscriptions not stored

2. SwiftUIBuilder

Purpose: Build UI iteratively with mock API data

How to use:

  • Each exercise is a complete, working implementation
  • Study the patterns, then try recreating from scratch
  • Modify and extend to practice variations
Section Exercises Patterns Covered
Lists Basic API List async/await data loading, error states
Pull to Refresh .refreshable, last-updated timestamp
Search & Filter .searchable, debounced search, combined filters
Grids Photo Grid LazyVGrid, category filtering, sheet presentation
Adaptive Grid GridItem(.adaptive), list/grid toggle with animation
Navigation Master-Detail NavigationLink(value:), navigationDestination
Modal Presentation .sheet, .fullScreenCover, .confirmationDialog, .alert
State Form Validation Real-time validation, password strength, submit gating
Shared State @StateObject, @EnvironmentObject, cart pattern

Shared Resources:

  • MockAPIService.swift — Actor-based mock API with simulated delays and random failures
  • Models: User, Post, Photo, Product

3. TestabilityWorkshop

Purpose: Refactor untestable code and write comprehensive tests

How to use:

  1. Read the "Before" (untestable) code in each exercise
  2. Study the "After" (testable) refactored version
  3. Examine the corresponding test file
  4. Practice writing tests yourself before looking at solutions
  5. Run tests with Cmd+U
Section Exercise Refactoring Pattern
Dependency Injection Singleton Dependencies Extract protocols, inject via initializer
Network Coupling HTTPClient protocol, mock responses
Date/Time DateProviding protocol, controllable time
Side Effects UserDefaults KeyValueStore protocol, in-memory store
File System FileSystemProtocol, in-memory fake
Architecture ViewModel Testing @MainActor, state transitions, @Published
Protocol Mocking Spy/Stub/Fake patterns, call verification
Async Async/Await Testing Async test methods, Task cancellation

Test Target Structure:

TestabilityWorkshopTests/
├── Mocks/TestMocks.swift    # Reusable mock implementations
├── SingletonExerciseTests.swift
├── NetworkCouplingExerciseTests.swift
├── DateTimeExerciseTests.swift
├── UserDefaultsExerciseTests.swift
├── FileSystemExerciseTests.swift
├── ViewModelExerciseTests.swift
├── ProtocolMockingExerciseTests.swift
└── AsyncTestingExerciseTests.swift

4. ConcurrencyWorkshop

Purpose: Deep-dive into Swift Concurrency and Combine with interactive learning

How to use:

  • Each module has three tabs: Try It (interactive demo), Learn (Q&A), Code (full source)
  • Run the demos to see concurrency patterns in action
  • Study the Q&A section for conceptual understanding
  • Review the source code and try exercises
Section Modules Patterns Covered
AsyncSequences Consuming AsyncSequence for await, cancellation, breaking early
AsyncStream yield, finish, onTermination, error handling
Bridging Delegates Wrapping delegate APIs with continuations
Continuations Checked & Unsafe withCheckedContinuation, timeout patterns, one-resume rule
Combine Operators Combining Publishers combineLatest, merge, zip
Transforming Streams flatMap, switchToLatest, schedulers
Sendable Thread Safety Sendable protocol, @unchecked Sendable, crossing isolation
MainActor UI Patterns @MainActor, nonisolated, Swift 6 strict concurrency

Module Structure:

  • Each view includes working code examples you can run
  • Q&A sections explain the "why" behind each pattern
  • Exercises challenge you to extend or modify the code

Topics Covered

Concurrency

  • GCD: DispatchQueue, serial vs concurrent, sync vs async
  • Race conditions and data races
  • Main thread safety for UI updates
  • Deadlocks (queue reentry, lock ordering)
  • Swift Concurrency: async/await, Task, TaskGroup
  • Task cancellation and cooperative cancellation
  • Actor isolation and reentrancy
  • Structured vs unstructured concurrency
  • Combine: Publishers, Subscribers, AnyCancellable, retain cycles
  • AsyncSequence and for await loops
  • AsyncStream for bridging imperative code
  • Continuations: withCheckedContinuation, withUnsafeContinuation
  • Sendable protocol and thread-safe types
  • @MainActor and UI isolation patterns
  • Swift 6 strict concurrency preparation

SwiftUI

  • State management: @State, @Binding, @StateObject, @ObservedObject, @EnvironmentObject
  • Lists and ForEach
  • LazyVGrid/LazyHGrid with GridItem
  • Navigation: NavigationStack, NavigationLink, navigationDestination
  • Sheets, full-screen covers, alerts, confirmation dialogs
  • .searchable and .refreshable modifiers
  • .task for async data loading
  • Form validation patterns
  • Animations and transitions

Testing (XCTest)

  • Test structure: Arrange-Act-Assert
  • setUp() and tearDown()
  • Dependency injection for testability
  • Protocol-based mocking (Stub, Spy, Fake)
  • Testing @Published properties
  • @MainActor test classes for ViewModels
  • Async test methods (func test_x() async)
  • Testing error cases with XCTAssertThrowsError
  • Verifying mock interactions (call counts, arguments)

Swift Fundamentals (embedded throughout)

  • Protocols and protocol extensions
  • Generics
  • Value types vs reference types
  • Access control
  • Error handling
  • Closures and capture lists ([weak self])
  • Codable
  • Result type

Interview Practice Tips

For Code Review (ConcurrencyBugHunt)

  1. Read systematically — Don't jump to conclusions
  2. Look for shared mutable state — Who reads? Who writes? When?
  3. Trace the thread — Which queue/actor is this running on?
  4. Check completion handlers — Are they always called? Only once?
  5. Verify cancellation — Is Task.isCancelled checked after awaits?

For Building UI (SwiftUIBuilder)

  1. Start with the data model — What state do you need?
  2. Choose the right property wrapper — Who owns this state?
  3. Handle loading/error/empty states — Always show something
  4. Test on device — Simulators hide performance issues

For Testing (TestabilityWorkshop)

  1. Test behavior, not implementation — What should happen, not how
  2. One assertion focus per test — Tests should fail for one reason
  3. Use descriptive test namestest_methodName_condition_expectedResult
  4. Inject everything — If you can't inject it, you can't test it
  5. Reset mocks in tearDown — Tests must be independent

Running the Projects

# Open in Xcode
open ConcurrencyBugHunt/ConcurrencyBugHunt.xcodeproj
open SwiftUIBuilder/SwiftUIBuilder.xcodeproj
open TestabilityWorkshop/TestabilityWorkshop.xcodeproj
open ConcurrencyWorkshop/ConcurrencyWorkshop.xcodeproj

# Run tests (TestabilityWorkshop)
# Cmd+U in Xcode, or:
xcodebuild test -project TestabilityWorkshop/TestabilityWorkshop.xcodeproj \
  -scheme TestabilityWorkshop \
  -destination 'platform=iOS Simulator,name=iPhone 15'

File Structure

iOS-Practice/
├── README.md                          # This file
├── ConcurrencyBugHunt/
│   ├── ConcurrencyBugHuntApp.swift
│   ├── ContentView.swift
│   └── Exercises/
│       ├── GCD/
│       ├── AsyncAwait/
│       └── Combine/
├── SwiftUIBuilder/
│   ├── SwiftUIBuilderApp.swift
│   ├── ContentView.swift
│   ├── Shared/MockAPIService.swift
│   └── Exercises/
│       ├── List/
│       ├── Grid/
│       ├── Navigation/
│       └── State/
├── TestabilityWorkshop/
│   ├── TestabilityWorkshopApp.swift
│   ├── ContentView.swift
│   ├── Exercises/
│   │   ├── DependencyInjection/
│   │   ├── SideEffects/
│   │   ├── Architecture/
│   │   └── Async/
│   └── TestabilityWorkshopTests/
│       ├── Mocks/TestMocks.swift
│       └── *Tests.swift
└── ConcurrencyWorkshop/
    ├── ConcurrencyWorkshopApp.swift
    ├── ContentView.swift
    ├── Shared/                        # Reusable tab views, code viewer
    ├── ModuleContent/                 # Q&A and exercise content
    └── Modules/
        ├── AsyncSequences/
        ├── Continuations/
        ├── CombineOperators/
        ├── Sendable/
        └── MainActor/

About

Practice problems to help you ace your interview!

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages