Custom View Modifiers & ViewBuilder

As your app grows you'll repeat the same styling and structure. SwiftUI lets you package reusable styles in a ViewModifier , expose them cleanly with View extensions, accept flexible content with @ViewBuilder , and extract repeated UI into reusable views. This is how you keep a large codebase DRY.

Learn Custom View Modifiers & ViewBuilder in our free Swift course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a…

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.

Building iOS Apps with SwiftUI • Intermediate

What You'll Learn in This Lesson

1️⃣ Custom ViewModifier

Conform a type to ViewModifier and implement body(content:) . The content parameter is the view you're modifying; return it wrapped with your changes. Apply it with .modifier(...) to reuse a consistent style everywhere.

2️⃣ A Clean API with a View Extension

Calling .modifier(CardStyle()) works but reads awkwardly. Add an extension on View with a convenience method so you can write .cardStyle() — exactly like a built-in modifier.

3️⃣ @ViewBuilder — Accepting Multiple Children

@ViewBuilder lets a closure return several views (and use if / switch ). It's why a VStack 's trailing closure can hold many children. Mark your own content closures with it to build flexible container views.

4️⃣ Extracting Reusable Views

When you repeat a chunk of UI, pull it into its own View struct that takes parameters. This keeps your code DRY, your body readable, and your styling consistent — and it pairs naturally with custom modifiers.

Your turn. Fill in the blanks to build a reusable pill style and expose it as .pillStyle() .

Create a TitledBox view that takes a title string and a @ViewBuilder content closure, showing the title above whatever views the caller passes. Then write a ViewModifier called RoundedBordered and expose it as .roundedBordered() . Use both together to build a tidy settings panel.

Practice quiz

What is a custom ViewModifier?

  • A new View
  • A reusable type that packages a set of modifications applied to a view
  • A property wrapper
  • A navigation link

Answer: A reusable type that packages a set of modifications applied to a view. A ViewModifier bundles modifications so you can reuse a consistent style across many views.

What method must a ViewModifier implement?

  • body(content:)
  • render()
  • draw()
  • init()

Answer: body(content:). A ViewModifier implements body(content:), returning the modified content.

What is the 'content' parameter in body(content:)?

  • A string
  • The view the modifier is applied to
  • A color
  • The parent view

Answer: The view the modifier is applied to. content is the view being modified; you return it wrapped with your changes.

How do you apply a custom ViewModifier to a view?

  • view.apply(MyModifier())
  • MyModifier(view)
  • view.modifier(MyModifier())
  • view + MyModifier()

Answer: view.modifier(MyModifier()). Call .modifier(MyModifier()) to apply a custom ViewModifier to any view.

What is a common way to make a modifier nicer to call?

  • Add a View extension method that calls .modifier(...)
  • Subclass View
  • Use a global function only
  • It cannot be improved

Answer: Add a View extension method that calls .modifier(...). An extension on View exposing a convenience method (e.g. .cardStyle()) reads cleanly.

What does @ViewBuilder do?

  • Builds the app
  • Compiles code
  • Stores state
  • Lets a closure return multiple child views (and use if/switch)

Answer: Lets a closure return multiple child views (and use if/switch). @ViewBuilder enables a closure to combine several views and use conditionals to build content.

Why can a VStack's trailing closure contain several views?

  • Because of @ViewBuilder on its content parameter
  • Because of @State
  • Because of @Binding
  • By accident

Answer: Because of @ViewBuilder on its content parameter. Container initializers mark their content closure @ViewBuilder, allowing multiple child views.

What is a clean way to reuse a chunk of UI?

  • Copy and paste it
  • Extract it into its own View struct (or a computed property)
  • Use a global variable
  • Inline everything

Answer: Extract it into its own View struct (or a computed property). Extracting repeated UI into a dedicated View struct keeps code DRY and readable.

Custom modifiers are most useful when you want to...

  • Apply the same group of styling repeatedly and consistently
  • Avoid using SwiftUI
  • Replace the View protocol
  • Disable previews

Answer: Apply the same group of styling repeatedly and consistently. They centralize a reusable style so it stays consistent and easy to change in one place.

A function or property marked @ViewBuilder can return what?

  • Only one view, ever
  • Several views combined into one result, with conditionals allowed
  • Only strings
  • Only numbers

Answer: Several views combined into one result, with conditionals allowed. @ViewBuilder composes the returned views into a single result and supports if/switch branches.