Skip to content
Prepare to Grow

iOS Architecture

Introduction to iOS Architecture

Understand architecture as deliberate decisions about responsibilities, dependencies, state, and change.

Advanced6 min read2 guided activities

Before you begin

What you will understand

  • Define software architecture in practical iOS terms.
  • Identify responsibilities, boundaries, and dependency relationships.
  • Distinguish architectural decisions from folder naming.
  • Evaluate architecture by changeability, clarity, and feedback speed.
01

Learning stage

Concept Explanation

Architecture is the set of decisions that determines where responsibilities live, how parts communicate, who owns state, and which direction dependencies point. An app has an architecture even when nobody designed one; accidental architecture simply makes those decisions inconsistently and discovers their cost later.

Useful boundaries isolate reasons to change. Presentation changes because product design changes, domain rules change because the business changes, and data access changes because APIs or storage change. These concerns do not need a layer for every type, but they should not be fused automatically inside one screen object.

Judge an architecture by the work it enables. Can a developer locate behavior, replace a dependency, test an important rule, understand state ownership, and add a feature without editing unrelated code? The best design is usually the smallest one that answers today's real pressures while leaving clear seams for likely change.

  • Responsibility: one reason a component exists and changes.
  • Boundary: a deliberate seam between concerns.
  • Dependency: one component's knowledge of or reliance on another.
  • State owner: the component responsible for a value's lifetime and mutations.
  • Composition root: the place where concrete dependencies are assembled.
  • Trade-off: a cost accepted to gain a specific benefit.
02

Learning stage

Syntax & Examples

A small feature becomes easier to reason about when loading, business decisions, and rendering have visible ownership.

CourseFeature.swiftswift
struct Course: Identifiable, Equatable {
  let id: UUID
  let title: String
  let completedLessons: Int
  let totalLessons: Int

  var canReceiveCertificate: Bool {
    totalLessons > 0 && completedLessons == totalLessons
  }
}

protocol CourseLoading {
  func courses() async throws -> [Course]
}

@MainActor
final class CourseListModel {
  enum State: Equatable {
    case idle, loading, loaded([Course]), failed(String)
  }

  private let loader: any CourseLoading
  private(set) var state: State = .idle

  init(loader: any CourseLoading) {
    self.loader = loader
  }

  func load() async {
    state = .loading
    do { state = .loaded(try await loader.courses()) }
    catch { state = .failed("Courses could not be loaded.") }
  }
}
The domain value owns its rule, the loading boundary hides data access, and the presentation model owns screen state.
03

Learning stage

Real-World Usage

Connect the architectural concept to maintainable iOS features and real change scenarios.

  • Change an API client without rewriting screen behavior.
  • Share business rules between UIKit and SwiftUI features.
  • Test loading, success, and failure without launching the app.
  • Give new team members predictable places to find state and behavior.
04

Learning stage

Common Mistakes

Identify abstractions and dependencies that add coupling, ambiguity, or unnecessary ceremony.

  • Treating an architecture diagram as proof that responsibilities are clear.
  • Creating a layer for every file regardless of change pressure.
  • Moving code between folders without changing dependency direction.
  • Hiding global singletons behind type aliases and calling it dependency injection.
  • Choosing a pattern before understanding the feature's state and workflows.
05

Learning stage

Practice Exercises

Apply the design to a small feature and evaluate it through observable change scenarios.

Activity 1

Map feature responsibilities

Choose a sign-in or course-list feature and list its UI state, domain decisions, data access, navigation, and side effects. Assign one owner to each.

Hint: If two components both believe they own the same state, make that conflict explicit.

Activity 2

Test the architecture with change

Ask how the design reacts to a new API, offline cache, alternate UI, and revised completion rule. Record which files should change for each scenario.

Hint: A good boundary contains change; it does not promise zero edits.

06

Learning stage

Knowledge Check

Answer each question before revealing the explanation.

QUESTION 1

Which description best defines application architecture?

  1. A.Decisions about responsibilities, state, boundaries, and dependencies
  2. B.A fixed list of folders
  3. C.The visual design system
  4. D.The number of source files
Reveal answer

Decisions about responsibilities, state, boundaries, and dependencies

Names and folders may communicate architecture, but the actual runtime relationships and ownership are what matter.

QUESTION 2

How should an architecture primarily be evaluated?

Reveal answer

By how clearly and safely it supports important behavior and likely change at an acceptable cost.

Pattern purity is less useful than understandable ownership, testable decisions, and fast feedback.

07

Learning stage

Interview Preparation

Explain the decision, dependency direction, trade-offs, and evidence—not only the pattern name.

What does good iOS architecture mean to you?

Short answer: Clear ownership and dependency boundaries that make important behavior easy to understand, test, and change without unnecessary ceremony.

Explore the detailed answer

I begin with feature workflows, state, side effects, and expected change. I keep domain decisions independent where that provides value, inject external dependencies, and let the UI render explicit state. I evaluate the result through change scenarios and tests, then add abstraction only when it removes demonstrated coupling or duplication.

Possible follow-ups

  • • Can a small app be over-architected?
  • • What signals tell you a boundary is missing?
08

Learning stage

Key Takeaways

Architecture is deliberate ownership and dependency design. Its value appears when behavior is understandable and change remains local, safe, and proportionate to the app's needs.

  • Every app has an architecture.
  • Boundaries should isolate genuine reasons to change.
  • State needs one clear owner.
  • Dependencies should be visible and replaceable where useful.
  • Choose the smallest design that handles real pressures.