What is the Content in SwiftUI
There is no actual Content
class or struct or type in SwiftUI
Content
is a generic, kinda like a "variable that holds a type"
Content
is simply being used to represent a type that conforms to the View
protocol (as in, a Button
and always a Button
, not Text
).
View
is not a class in SwiftUI; it is a protocol and behaves differently
Content
must always be the same type. Once a Button
, always a Button
. This is why sometimes you need to use AnyView
.
What is ViewModifier in Swift UI ?
ViewModifier
. ViewModifier
is a protocol. Other types can conform to ViewModifier
, but no variable or value can just have the plain type ViewModifier
.
To make a type conform to ViewModifier
, we define a body
method that takes a Content
(whatever that is) and returns a Body
(whatever that is):
func body(content: Content) -> Body
A ViewModifier
is essentially just this one method, that takes a Content
as input and returns a Body
as output.
What’s Body
? ViewModifier
defines it as an associatedtype
with a constraint:
associatedtype Body : View
This means we get to pick the specific type known as Body
in our ViewModifier
, and we can pick any type for Body
as long as it conforms to the View
protocol.
we find the true definition of ViewModifier
:
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public protocol ViewModifier {
static func _makeView(modifier: SwiftUI._GraphValue<Self>, inputs: SwiftUI._ViewInputs, body: @escaping (SwiftUI._Graph, SwiftUI._ViewInputs) -> SwiftUI._ViewOutputs) -> SwiftUI._ViewOutputs
static func _makeViewList(modifier: SwiftUI._GraphValue<Self>, inputs: SwiftUI._ViewListInputs, body: @escaping (SwiftUI._Graph, SwiftUI._ViewListInputs) -> SwiftUI._ViewListOutputs) -> SwiftUI._ViewListOutputs
associatedtype Body : SwiftUI.View
func body(content: Self.Content) -> Self.Body
typealias Content = SwiftUI._ViewModifier_Content<Self>
}
What is VStack in Swift UI ?
The VStack
type is a struct
, not a protocol. It is generic, which means it takes type parameters (just like a function takes function parameters). VStack
takes a single type parameter, named Content
. This means VStack
defines a family of types, one for every type it allows for Content
.
The whole reason to use a VStack
is to arrange multiple views in a column. The use of VStack
tells Swift to arrange its subviews vertically, and the VStack
's Content
type parameter specifies the types of the subviews.
For example, when you write this:
VStack {
Text("Hello")
Button(action: {}) {
Text("Tap Me!")
}
}
you’re actually creating an instance of this type:
VStack<TupleView<(Text, Button<Text>)>>
The Content
type parameter here is the type TupleView<(Text, Button<Text>)>
, which is itself a generic type TupleView
with its own type parameter named T
, and T
here is (Text, Button<Text>)
(a 2-tuple, also called a pair). So the VStack
part of the type tells SwiftUI to arrange the subviews vertically, and the TupleView<(Text, Button<Text>)>
part tells SwiftUI that there are two subviews: a Text
and a Button<Text>
.
we definitely want to let the compiler figure out these types for us. This is why Apple added the some View
syntax to Swift—so we can let the compiler figure out the exact type.
VStack is generic (and also limited to implementors of
View
), all it knows is that you've provided some specific type that implementsView
—and whatever type that is, we call itContent
.
Returning some View
has two important differences compared to just returning View
:
- We must always return the same type of view.
- Even though we don’t know what view type is going back, the compiler does.