← All daysDay 39 of 49 · Part 10: Architecture, testing, and performance
Day 39

Breaking a screen into small views · Passing dependencies

These are the lesson notes for this day. Its build-along tutorial and flash cards have not been written yet.

Lesson 44

Breaking a screen into small views

A large body is hard to read, slow for the compiler to type-check, and re-renders more than it needs to. Break a screen into small views with names, each taking only the data it needs. Extracting a subview costs almost nothing in SwiftUI, because a view is only a struct — and it improves performance, because SwiftUI can skip re-rendering a subview whose inputs did not change.

Some guidance on when to extract: when a piece of the screen has a name ("header", "price row"), when it repeats, or when body is longer than a screenful. Prefer a separate View struct to a computed property that returns some View, because only a struct gives SwiftUI a boundary at which it can skip an update.

Exercise

Take your largest view and split it into at least five named subviews without changing how it looks. Give each subview its own preview.

After this lesson you should be able to answer
  1. Why does extracting subviews improve performance?
  2. Why is a separate View struct better than a computed property for a large piece of interface?
  3. What should a subview receive as input?
Resources
Lesson 45

Passing dependencies

There are two ways to give a view what it needs. Pass it through the initializer when it is specific to that view and you want the dependency to be obvious. Put it in the environment when many views, at different depths, need the same thing — a theme, a data store, a network client. In both cases the view should not create its own dependencies or reach for a singleton. That is what makes it possible to preview and to test.

On architecture: SwiftUI works well with plain @Observable models owned by views, and does not require a view model for every screen. Add a view model when a screen has real logic that deserves tests. In an interview, be ready to explain that trade-off rather than to defend a single pattern.

Exercise

Give a screen its data source through the environment. Provide the real one in the app, and a fake one in previews and tests, changing only the place where it is injected.

After this lesson you should be able to answer
  1. When should a dependency be an initializer parameter, and when an environment value?
  2. Why are singletons a problem for previews and tests?
  3. When is a view model worth adding?
Resources