Using The @ViewBuilder Attribute Only When It's Absolutely Necessary
Daily Coding Tip 198
Celebrating 200 Daily Coding Tips š all tutorials will be free to all this week!
(Even though the 200th Daily Coding Tip isnāt until Wednesday š)
Apple has sent mixed messages about when and why the @ViewBuilder attribute is necessary.
When SwiftUI was first released, it was impossible to build a view without adding it to your body property. Apple then added the attribute to the body property inside in the View protocol, meaning that any conforming type secretly had the functionality without it being added manually.
Now that it was hidden away, it became quite ambiguous exactly what the some View type does, and whether it ever needs @ViewBuilder at all.
@ViewBuilder is an example of a result builder, which I covered in more detail in Daily Coding Tip 073. These attributes require the declaration of functions called buildBlock that take a bunch of parameters and condense them down into a single type. SwiftUI is actually heavily reliant on TupleView, which is an interesting type in itself.
Tuples are groups of values that may or may not have labels.
TupleView takes an associated generic type, but every tuple is different. Itās like being able to specialize with a bunch of generic types at once, which is usually impossible. What @ViewBuilder does is take the Button, Text and Image passed into a body property, which are not a single type, and converts them into a type like TupleView<(Button, Text, Image)>.
To demonstrate what happens when @ViewBuilder is not part of a protocol, Iāve created my own version of the View protocol that does not add the attribute.
Now my ConformingView needs @ViewBuilder on its body property, because this is no longer assumed by the protocol.
Iāve also provided an example of a situation when @ViewBuilder is not needed. When I compute the oneConcreteType property, I am actually returning a known type. Although some View is deliberately vague, this is mainly so that I can change the content of my Group and Swift will infer the type automatically.
If I explicitly stated the type as Group<TupleView<(Text, Text, Text)>>, I wouldn't need to use the opaque return type some View.
What if I then removed one Text?
I would need to manually change the type to Group<TupleView<(Text, Text)>>.
This would be pretty time consuming during the construction of a view, so itās obvious why Apple had to create the some keyword to deal with this situation.
Remember, an opaque return type means a single type needs to be returned, whether that be a Group or a layout type like VStack or HStack.
If you insist on returning multiple views, for instance to populate a VStack or HStack elsewhere with content, youāll need to add @ViewBuilder unless itās inside the body property where @ViewBuilder is automatically provided.



