Reputation: 1763
My curiosity takes me to pass a View
type as parameter to @ViewBuilder
. Passing a Model/Primitive type as param in @ViewBuilder
is perfectly valid.
As shown below code.
struct TestView<Content: View>: View {
let content: (String) -> Content
init(@ViewBuilder content: @escaping (String) -> Content) {
self.content = content
}
var body: some View {
content("Some text")
}
}
struct ContentTestView: View {
var body: some View {
TestView {
Text("\($0)")
}
}
}
In place of String
in
let content: (String) -> Content
If I try to pass a SwiftUI View
type, then Compiler is not happy with it.
let content: (View) -> Content
Even though params for @ViewBuilder
accepts custom Protocol type like Searchable
but not View
protocol.
compiler tell me this Protocol 'View' can only be used as a generic constraint because it has Self or associated type requirements
My whole idea is that content
can be allowed to hold Section/List/Text
in it.
Edit: I expected code like below.
struct TestView<Content: View>: View {
let content: (View) -> Content
init(@ViewBuilder content: @escaping (View) -> Content) {
self.content = content
}
var body: some View {
content(
List {
ForEach(0..<10) { i in
Text(\(i))
}
}
)
}
}
struct ContentTestView: View {
var body: some View {
TestView { viewbody -> _ in
Section(header: Text("Header goes here")) {
viewbody
}
}
}
}
Any way can I achieve this ?
Upvotes: 6
Views: 6603
Reputation: 30746
Custom inits are longer required for this, e.g.
struct TestView<Content>: View where Content: View {
@ViewBuilder let content: (String) -> Content
var body: some View {
content("Some text")
}
}
Upvotes: 0
Reputation: 258413
The possible solution is to use AnyView
, like
struct TestView<Content: View>: View {
let content: (AnyView) -> Content
init(@ViewBuilder content: @escaping (AnyView) -> Content) {
self.content = content
}
var body: some View {
content(AnyView(
Text("Demo") // << put here any view hierarchy
))
}
}
Upvotes: 4