What gets returned in SwiftUI View?
from a technical pov, a View is a protocol that has an associated type body that conforms to View.
We know a SwiftUI body will return any value that conforms to the View Protocol for more details you can read about the opaque types.
but what type is inferred let’s find out. I use Mirror API to print the type returned you can read more about it in this article.
what does Text return?
let’s take an example of a text. so based on what is printed we know Text
returns Text
which conform to the a View
somewhere in the code.
but strangely when we change the padding we get something strange.
interestingly it stopped being a text and became a Modified Content so the question now is What is Modified Content?
Understanding ModifiedContent
ModifiedContent
is a generic struct that takes two type parameters: Content
and Modifier
. The Content
type is the original view that you're modifying, and Modifier
is a type that conforms to the ViewModifier
protocol, which defines how the original view should be modified.
ModifiedContent<Text(Content), _PaddingLayout(modifier)>
The Text is the content and Padding is a modifier. The documentation of ModifiedContent is also very helpful:
If
content
is aView
andmodifier
is aViewModifier
, the result is aView
. Ifcontent
andmodifier
are both view modifiers, then the result is a newViewModifier
combining them.
it’s also important to know that ModifiedContent
is a view
so we can return this to our SwiftUI body.
To learn more details about ViewModifiers you can read it here.
let’s understand the above statement.
1- If content
is a View
and modifier
is a ViewModifier
, the result is a View.
so if we look at the return type below we get ModifiedContent<Text(Content), _PaddingLayout(modifier)>
so content
here is text
which is a view
and view modifier
here is padding
hence we have ModifiedContent
back which is also view
that gets displayed by SwiftUI.
2- If content
and modifier
are both view modifiers, then the result is a new ViewModifier
combining them.
if we add a background to the above example and look at the debugger
now our content
is modified content
and a modifier
is a background viewmodifier
which combines to also form a modified content
which is a combinedViewModifier
containing the values of both padding and background. as you can see below ModifiedContent
is also a ViewModifier
so things are quite messy but we figured out that ViewModifier is a protocol whose eventual result should be a View. It can be concatenated or transformed using other ViewModifiers, but we end up as a View at some point.
what about Content?
Content appears to be a typealias defined in ViewModifier, but Apple doesn't tell us the type. Content
is used everywhere in the SwiftUI library, I used this technique to figure out what Content is from SwiftUI interface.
we can see that Content
is an alias for _ViewModifier_Content<Self>
, which is a struct
that conforms to a View.
Summary
Content conforms to View and ViewModifier doesn’t necessarily need to conform to View, but it needs to return a View at some point. We can’t keep returning ViewModifiers because they’re not Views. This is how SwiftUI keeps adding Views with different modifiers as in the end we return a View which is basically what the SwiftUI body needs.
SwiftUI has a lot of mystery behind the scenes and this was just the tip of the iceberg. Apple wants us to just write SwiftUI code and not worry about the technicalities of rendering your content, however, it comes with the disadvantages of not knowing how everything works behind the scenes.
References:
https://developer.apple.com/documentation/swiftui/viewmodifier