Why Self.Content is a typealias while Self.Body is an associatedtype ? What's the difference?
Because Content is a typealias, the author of the ViewModifier protocol gets to pick the type being aliased when she writes the protocol. (You can't see the type being aliased because that type is _ViewModifier_Content<Self>. When an identifier in the SDK starts with _, Apple omits the identifier from documentation and generated interfaces.)
Because Body is an associatedtype, you get to pick the type that it aliases, when you write a type that conforms to the ViewModifier protocol. You can make Body be any type you want, subject to two conditions:
You must pick a type that conforms to View (because the ViewModifier protocol constrains Body to conform to View).
You must be able to create or obtain an instance of whatever type you pick, because you have to return an instance of it from the body method. (Or you could crash or hang to avoid returning at all, but that's usually not what you want…)
So, when you implement a type conforming to ViewModifier, you cannot influence what Content means. It always means _ViewModifier_Content<Self>. But you can choose what Body means, by choosing the return type of the body method.
Here's I'll force Body to mean EmptyView:
struct EmptyModifier: ViewModifier {
func body(content: Content) -> EmptyView {
EmptyView()
}
}
And here I'll force Body to mean Color:
struct RedModifier: ViewModifier {
func body(content: Content) -> Color {
Color.red
}
}
Usually we use some View as the type, which means that Swift deduces the exact type for us and keeps it a secret:
struct FrameModifier: ViewModifier {
var color: Color
var width: CGFloat
func body(content: Content) -> some View {
return content
.padding(width)
.border(color, width: width)
}
}
Here, all we know about the Body type is that it conforms to View. Swift tries pretty hard to keep us from finding out the real type at compile time.