SwiftUI simple viewBuilder practical usage guide

How to use @ViewBuilder in your SwiftUI projects

Ghazi Tozri
3 min readDec 19, 2022
Professional programmer teaching a junior developer how to use @ViewBuilder
by Alvaro Reyes — unsplash

Fundamentals

@ViewBuilder is a function builder in SwiftUI that allows you to create views by composing smaller views. It is typically used to create custom views that can build and combine other views to create their own complex layout.

Apple defines it in its documentation as : A custom parameter attribute that constructs views from closures.

Many of the built-in views in SwiftUI that we use all the time, implements@ViewBuilder to compose their subviews and layouts. For example, the VStack view, which arranges its subviews in a vertical stack, uses @ViewBuilder to build its layout from the subviews it is given.

Actually, you can open any of your SwiftUI structs that conforms to View protocol, it necessary has a body. If you jump to its definition you will find that body is actually returning a @ViewBuilder , we just tend not to write explicitly and let SwiftUI handles it, here is an example :

Usage

@ViewBuilder is an important part of the SwiftUI framework because it allows you to create custom views that can build and combine other views to create complex layouts. This makes it much easier to create and reuse view hierarchies in your app, which can help to improve code reuse and maintainability.

Constructing View

In this example, the CustomView struct accepts a closure containing a view hierarchy as a parameter in its initializer. The closure is marked with the @ViewBuilder attribute, which allows you to write the closure in a more concise and declarative style, without having to explicitly wrap each view in a closure.

To use this CustomView, you would create an instance of it and provide it with a closure containing the views you want to include in the view hierarchy.

Wrapping Views

In this example, the WrapperView struct takes a generic Content parameter that specifies the type of view that it will wrap. The content parameter of the initializer is marked with the @ViewBuilder attribute, which allows you to pass in a closure containing the view you want to wrap.

To use this WrapperView, you would create an instance of it and provide it with a closure containing the view you want to wrap and applying that padding, background, cornerRadius etc.. modifiers to it, without needing to write them every time on different views, just wrap them !

Custom Modifiers

You can use @ViewBuilder to create custom view modifiers that build and combine other views to create their layout. Here is an example of how you might use @ViewBuilder to create a custom view modifier that adds a border and a drop shadow to the view it is applied to:

In this example, the ShadowBorderModifier struct defines a custom view modifier that adds a black border and a drop shadow to the view it is applied to. The body method of the ShadowBorderModifier is marked with the @ViewBuilder attribute, which allows you to build and combine views inside the method body.

To use this ShadowBorderModifier, you would apply it to a view using the .modifier() method. Or in my case, i made an extension of View that returns a ModifierContent as the ShadowBorderModifier.

Tips

Here are a few tips and things to consider when using @ViewBuilder in your code:

  1. When using @ViewBuilder, be sure to mark the closure, initializer, or method that contains the view hierarchy with the @ViewBuilder attribute. This will allow you to use @ViewBuilder to build and combine views inside that closure, initializer, or method.
  2. If the closure, initializer, or method that contains the view hierarchy is marked with the @escaping attribute, be sure to include that attribute when you apply the @ViewBuilder attribute. This is necessary because the view hierarchy will be calculated asynchronously, and the closure may be called at any time after the initializer has finished.
  3. When using @ViewBuilder to build and combine views, be sure to use the correct return type for the closure, initializer, or method that contains the view hierarchy. This should typically be some View, which indicates that the view hierarchy can contain multiple views of any type.

Thanks for reading.

--

--

Ghazi Tozri

I write about Apple news, Swift, and SwiftUI in particular, and technology in general.