Что вы имеете в виду, вероятно, это:
init<T: View>(withHeader headerText: String, @ViewBuilder _ content: @escaping () -> T)
where Content == VStack<TupleView<(Text, T)>> {
self.init {
VStack(alignment: .leading) {
Text(headerText)
.font(.headline)
content()
}
}
}
Представление, созданное этим инициализатором, всегда будет иметь форму (И да)
InfoBox<VStack<TupleView<(Text, SomeOtherView)>>>
Другими словами, этот init решает, что Content
должно быть. Так что это применимо только к InfoBox
es с Content == ThatLongTypeName
, отсюда и ограничение.
Обратите внимание, что вызывающая сторона может указать тип SomeOtherView
, но это не Content
! Content
- это VStack<TupleView<(Text, SomeOtherView)>>
. Поэтому добавляется дополнительный универсальный параметр c и тип возвращаемого значения замыкания изменяется.
IMO, было бы намного проще, если бы вы просто сделали это:
struct Infobox<Content>: View where Content: View {
let content: () -> Content
let headerText: String
var body: some View {
VStack(alignment: .leading) {
if !headerText.isEmpty {
Text(headerText)
.font(.headline)
}
content()
}
}
// note the optional parameter here
init(withHeader headerText: String = "", @ViewBuilder _ content: @escaping () -> Content) {
self.content = content
self.headerText = headerText
}
}