I have a view that return a view in form of <TupleView<(View, View)>>
, like this:
Also I have a view that return a view in form of <_>
, like this:
With knowing that both way works and my wished way is using TupleView under cover but having the look of <_>
, I tried to work on MyView3, as you can see in my tried codes I want this look of (content: () -> _) -> MyView3<_>
for being more simple and understandable, but i need TupleView way initialization undercover. I got 3 error's for MyView3 to make it work. Do you think is there a way for my goal?
For more information see this codes:
struct ContentView: View {
var body: some View {
MyView1(content: {
Text("Text 1").fixedSize()
Text("Text 2").fixedSize()
})
.padding()
MyView2(tupleViewContent: {
Text("Text 3").fixedSize()
Text("Text 4").fixedSize()
})
.padding()
// This part has issue!
MyView3(content: {
Text("Text 5").fixedSize()
Text("Text 6").fixedSize()
})
.padding()
}
}
struct MyView1<Content: View>: View {
let content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
var body: some View {
content()
}
}
struct MyView2<Content: View>: View {
let content: () -> Content
init<Content1: View, Content2: View>(@ViewBuilder tupleViewContent: @escaping () -> Content) where Content == TupleView<(Content1, Content2)> {
self.content = tupleViewContent
}
var body: some View {
content()
}
}
struct MyView3<Content: View>: View {
let content: () -> Content
private init<Content1: View, Content2: View>(@ViewBuilder tupleViewContent: @escaping () -> Content) where Content == TupleView<(Content1, Content2)> {
self.content = tupleViewContent
}
init(@ViewBuilder content: @escaping () -> Content) {
//Error:
// Generic parameter 'Content1' could not be inferred
// Generic parameter 'Content2' could not be inferred
// Initializer 'init(tupleViewContent:)' requires the types 'Content' and 'TupleView<(Content1, Content2)>' be equivalent
self.init(tupleViewContent: content)
}
var body: some View {
content()
}
}
CodePudding user response:
The generics is resolved at compilation time, so init/s should go from more specific to more common (finally to the designated one).
In your case it should be like (tested with Xcode 13.2)
struct MyView3<Content: View>: View {
let content: () -> Content
init<Content1: View, Content2: View>(@ViewBuilder tupleViewContent: @escaping () -> Content) where Content == TupleView<(Content1, Content2)> {
self.init(content: tupleViewContent)
}
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
var body: some View {
content()
}
}