There are many ways that closures can be passed as arguments to an initializer. When I use layout types like VStack it’s obvious that I’m not using the initializer syntax as written:
VStack(alignment: .center, spacing: nil, content: { Text("Hello") })Since the first two parameters have default values, they don’t need to be included, so this can be shortened:
VStack(content: { Text("Hello") })Note that the content parameter label is required, because otherwise the compiler doesn’t know which of the parameters you’re passing in anonymously.
Instead of passing parameters in the brackets, I can close the brackets and add the closure at the end:
VStack() { Text("Hello") }This is a trailing closure.
You’re probably aware that the opening and closing brackets at the end of VStack() can also be omitted, and that’s how SwiftUI is usually written. But I thought I’d go over the definition of a trailing closure, before I provide some examples of how to use them.
I’m starting with a type, appropriately called TrailingClosureExample, which has 3 closures as properties.
The first example, noBrackets, proves that it’s possible to create a TrailingClosureExample without any brackets. The first trailing closure does not need a label here, just as the body of a VStack does not need to be labelled as content. This is the opposite of bracketsEnclosingParameters, where all of the parameters are inside the brackets.
Commas are only necessary for closures that are inside brackets.
I guess this technically isn’t an example of trailing closures, because you’re simply passing a bunch of closures as parameters.
Finally bracketsEnclosingFirstParameter is halfway between these extremes, with the first closure inside the brackets while subsequent closures are trailing.
See how closure1 needs to be labelled, but closure2 doesn’t?
The first trailing closure never needs a label, even if other closures were passed inside the brackets, but all subsequent closures do.
Every structure has an automatically generated memberwise initializer, which is why I didn’t have to specify an initializer for TrailingClosureExample.
Now I have another structure called TrailingClosureExample2 that declares an explicit initializer that makes closure1 anonymous by using an underscore like _ for the label.
This means that I won’t need to label it as closure1.
This sneaky trick allows me to break the rules on labelling.
Even if I’m enclosing all of my parameters in brackets, or perhaps just the first one, I do not need to label the first closure in this case.



