App Architecture with MVVM

A clean architecture keeps apps maintainable as they grow. In this final lesson you'll structure a SwiftUI app with MVVM — separating the Model , View , and ViewModel — using ObservableObject view models for separation of concerns and easy testing.

Learn App Architecture with MVVM in our free Swift course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…

Part of the free Swift course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

1️⃣ The Model

The Model is pure data and domain rules. It imports no UI framework, so it can be reused and tested anywhere.

2️⃣ The ViewModel

The ViewModel is an ObservableObject that prepares model data for the view and holds presentation logic. Its @Published state drives the UI.

Your turn. Fill in the protocol and the publishing wrapper.

3️⃣ The View (and Testing the ViewModel)

The View stays thin: it shows ViewModel state and forwards actions. Because the ViewModel is UI-independent, you can unit-test its logic directly with XCTest.

Now you try. Fill in the wrapper that owns the view model and the method call.

📋 Quick Reference: MVVM Recap

Structure a small weather screen as Model, ViewModel, and View, then test the ViewModel — the perfect capstone for the track.

Practice quiz

What do the three letters in MVVM stand for?

  • Model-View-ViewModel
  • Model-Value-View-Module
  • Main-View-Model-Manager
  • Module-View-ViewMaker

Answer: Model-View-ViewModel. MVVM is Model, View, and ViewModel.

What is the Model's responsibility?

  • Drawing the UI
  • Representing the app's data and business rules
  • Handling taps
  • Storing view state only

Answer: Representing the app's data and business rules. The Model holds data and domain logic, independent of the UI.

What does the View do in MVVM?

  • Stores the database
  • Displays state and forwards user actions
  • Performs networking
  • Owns business rules

Answer: Displays state and forwards user actions. The View shows what the ViewModel exposes and relays user input.

What is the ViewModel's job?

  • Render pixels
  • Prepare data for the view and hold presentation logic
  • Define the storage schema
  • Replace the Model entirely

Answer: Prepare data for the view and hold presentation logic. The ViewModel transforms model data into view-ready state and handles presentation logic.

Which protocol do SwiftUI view models commonly adopt?

  • Codable
  • Hashable
  • ObservableObject
  • Sendable

Answer: ObservableObject. ObservableObject lets a view model publish changes that the view observes.

Inside an ObservableObject, which wrapper publishes a property's changes?

  • @State
  • @Published
  • @Binding
  • @Environment

Answer: @Published. @Published broadcasts changes so observing views refresh.

Which wrapper does a SwiftUI view use to observe a view model it creates and owns?

  • @State
  • @StateObject
  • @Published
  • @FetchRequest

Answer: @StateObject. @StateObject creates and owns an ObservableObject for the view's lifetime.

A key benefit of MVVM is...

  • Fewer files always
  • No need for models
  • Faster compile times guaranteed
  • Separation of concerns and easier testing of logic

Answer: Separation of concerns and easier testing of logic. MVVM separates UI from logic, making the logic easy to test in isolation.

Why is a ViewModel easy to unit test?

  • It holds plain logic with no UI dependency
  • It imports SwiftUI heavily
  • It runs on the GPU
  • It cannot be tested

Answer: It holds plain logic with no UI dependency. Because a ViewModel is UI-independent, you can test its logic directly without rendering views.

In MVVM, the View should ideally contain...

  • All business logic
  • The data model
  • Little logic — mostly layout bound to ViewModel state
  • The networking code

Answer: Little logic — mostly layout bound to ViewModel state. Views stay thin, delegating logic to the ViewModel for testability and clarity.