MVC, MVVM, VIPER and TCA compared

Architecture & patterns Senior Swift 5.9+ iOS 17+ Reviewed By Alok Singh

Pick the fix

A team of three is building a new SwiftUI app with about 10 screens. What is a sensible default?

Options
Hint 1 of 1

Match ceremony to team size.

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A MVVM, or plain @Observable feature models, with injected services

Correct. It's testable with little ceremony and fits SwiftUI's data flow.

Why not the others?
  • B VIPER for every screen. Five types per screen is heavy for a small team.
  • C Put all logic in the views. It's hard to test, and views grow large.
  • D TCA, because it is the most modern. It can work, but the choice should come from needs, not novelty.

30-second answer

All of them separate UI from logic; they differ in how many layers there are and how strict the data flow is. MVC is simple but controllers grow big. MVVM moves presentation logic into a testable view model and fits SwiftUI well. VIPER splits every screen into five roles, which suits large teams at a high boilerplate cost. TCA enforces one-way state, actions and reducers with strong testing support, but you depend on a library. Choose by team size, testability needs and how much ceremony you can afford.

Practise saying it · 60 s. No recording, just a timer

Compare the main iOS architectures.

Say your answer out loud, then check which of these points you covered:

  • Separation of concerns
  • Trade-offs of each
  • Team and app size
  • Navigation

Deep dive

In SwiftUI, a plain @Observable model per feature (often called MV) is often enough.

Consistency across a codebase matters more than the pattern chosen.

Navigation is the part most patterns leave unsolved, hence coordinators and routers.

Mixing patterns per feature is fine if boundaries are clear.

PatternStrengthCost
MVCSimple, Apple's defaultMassive view controllers
MVPTestable presenterLots of view protocols
MVVMTestable, fits SwiftUINavigation left open
VIPERStrict roles, large teamsHeavy boilerplate
TCAOne-way flow, exhaustive testsLibrary dependency, learning curve

Common mistakes

  • Picking VIPER for a small app.
  • Calling any class with 'ViewModel' in its name MVVM.

Senior take & follow-ups

Seniors argue trade-offs for a specific team and app, not which pattern is best.

Follow-up questions

Think of your answer first, then open the hint.

  1. Where does navigation live in MVVM?

    Show hint

    A coordinator or router, not the view model's UI code.

  2. What does TCA give you?

    Show hint

    Predictable state changes and exhaustive tests.

Suggest a fix if something here is wrong or out of date.