SwiftUI:从另一个初始化程序调用它时,如何使我的闭包 return 'Content' 而不是 'some View'?
SwiftUI: How do I make my closure return 'Content' instead of 'some View' when calling it from another initialiser?
我目前正在学习SwiftUI,我运行陷入了一个问题。
在下面的代码中,我有两个初始化器。第一个有效(假设我注释掉第二个足够长的时间来测试代码)。第二个没有。它会抛出一个编译器错误,提示“无法将类型 'some View' 的值分配给类型 'Content'。”
我在这里做错了什么?我能够使用 Infobox() { Text("Some Text") }
从结构外部成功调用第一个初始化程序,在我看来,这与我尝试从第二个初始化程序调用它时使用的语法完全相同。不管我 google 有多少,我似乎都想不通。
如果您能提供任何帮助,我将不胜感激。
struct Infobox<Content>: View where Content: View {
let content: Content
var body: some View {
content
}
init(@ViewBuilder _ content: @escaping () -> Content) {
self.content = content()
}
init(withHeader headerText: String, @ViewBuilder _ content: @escaping () -> Content) {
self.init() {
VStack(alignment: .leading) {
Text(headerText)
.font(.headline)
}
content()
}
}
}
}
你的意思大概是这样的:
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 with Content == ThatLongTypeName
,因此约束。
注意调用者可以指定SomeOtherView
的类型,但那不是Content
! Content
是 VStack<TupleView<(Text, SomeOtherView)>>
。因此,多加了一个泛型参数,闭包return类型发生了变化。
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
}
}
我目前正在学习SwiftUI,我运行陷入了一个问题。
在下面的代码中,我有两个初始化器。第一个有效(假设我注释掉第二个足够长的时间来测试代码)。第二个没有。它会抛出一个编译器错误,提示“无法将类型 'some View' 的值分配给类型 'Content'。”
我在这里做错了什么?我能够使用 Infobox() { Text("Some Text") }
从结构外部成功调用第一个初始化程序,在我看来,这与我尝试从第二个初始化程序调用它时使用的语法完全相同。不管我 google 有多少,我似乎都想不通。
如果您能提供任何帮助,我将不胜感激。
struct Infobox<Content>: View where Content: View {
let content: Content
var body: some View {
content
}
init(@ViewBuilder _ content: @escaping () -> Content) {
self.content = content()
}
init(withHeader headerText: String, @ViewBuilder _ content: @escaping () -> Content) {
self.init() {
VStack(alignment: .leading) {
Text(headerText)
.font(.headline)
}
content()
}
}
}
}
你的意思大概是这样的:
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 with Content == ThatLongTypeName
,因此约束。
注意调用者可以指定SomeOtherView
的类型,但那不是Content
! Content
是 VStack<TupleView<(Text, SomeOtherView)>>
。因此,多加了一个泛型参数,闭包return类型发生了变化。
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
}
}