У меня есть представление, которое возвращает представление в виде <TupleView<(View, View)>>
, например:
Также у меня есть представление, которое возвращает представление в виде <_>
, например:
Зная, что оба способа работают, и мой желаемый способ - использовать TupleView под прикрытием, но имея вид <_>
, я попытался работать с MyView3, как вы можете видеть в моих проверенных кодах, я хочу, чтобы этот вид (content: () -> _) -> MyView3<_>
был более простым и понятным, но мне нужна скрытая инициализация TupleView. Я получил 3 ошибки для MyView3, чтобы заставить его работать. Как вы думаете, есть ли путь к моей цели?
Для получения дополнительной информации см. эти коды:
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()
}
}
Генерики разрешаются во время компиляции, поэтому инициализация должна идти от более конкретного к более общему (наконец, к назначенному).
В вашем случае это должно быть так (проверено с 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()
}
}
Это бесполезно приватно, потому что быстрый компилятор пытается разрешить необходимый инициализатор во время компиляции клиента этого API, а не во время выполнения или внутри, поэтому он должен иметь такую же видимость, как и любой инициализатор.
Спасибо, мне нужно было, чтобы инициализация tupleView была приватной, как вы думаете, это возможно?