Using the declaration of VStack
we need to use @ViewBuilder
for our content parameter. It is a closure but it shouldn't be @escaping it won't be good to store closure if we need only data from it. I assume that from the Apple declarations.
Also I believe that @inlinable
is important because:
The @inlinable attribute exports the body of a function as part of a
module's interface, making it available to the optimizer when
referenced from other modules.
More info here
struct Layout <Content> : View where Content : View {
var content: Content
@inlinable public init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body : some View {
VStack {
Text("This is a layout")
self.content
}
}
}
To use it:
Layout {
Text("1")
VStack {
Text("1")
Text("2")
}
}
Update: As Matteo Pacini noted as a misleading info about @escaping
.
We need to use @escaping
for DynamicViewContent
views.
@escaping
is used Apple's View structures for view structs that are accepting Collections(Array, Range, etc). Because the ForEach
implements DynamicViewContent
- a type of view that generates views from an underlying collection of data. List
in its initializers also ForEach
in Content
public init<Data, RowContent>(_ data: Data, selection: Binding<Selection>?, action: @escaping (Data.Element.IdentifiedValue) -> Void, rowContent: @escaping (Data.Element.IdentifiedValue) -> RowContent) where Content == ForEach<Data, Button<HStack<RowContent>>>, Data : RandomAccessCollection, RowContent : View, Data.Element : Identifiable