在SwiftUI中是否可以有一个可选的@ViewBuilder
闭包?例如,假设我要开发一个自定义视图,该视图需要两个这样的视图构建器闭包:
import SwiftUI
struct TopAndBottomView<Content>: View where Content: View {
let topContent: () -> Content
let bottomContent: () -> Content
init(@ViewBuilder topContent: @escaping () -> Content, @ViewBuilder bottomContent: @escaping () -> Content) {
self.topContent = topContent
self.bottomContent = bottomContent
}
var body: some View {
VStack {
topContent()
Spacer()
bottomContent()
}
}
}
struct TopAndBottomView_Previews: PreviewProvider {
static var previews: some View {
TopAndBottomView(topContent: {
Text("TOP")
}, bottomContent: {
Text("BOTTOM")
})
}
}
但是我希望底视图是可选的。我尝试过:
struct TopAndBottomView<Content>: View where Content: View {
let topContent: () -> Content
let bottomContent: (() -> Content)?
init(@ViewBuilder topContent: @escaping () -> Content, @ViewBuilder bottomContent: (() -> Content)? = nil) {
self.topContent = topContent
self.bottomContent = bottomContent
}
var body: some View {
VStack {
topContent()
Spacer()
if bottomContent != nil {
bottomContent!()
}
}
}
}
但我收到此错误:
函数生成器属性'ViewBuilder'只能应用于函数类型的参数。
谢谢。
似乎您在初始化程序中不需要@ViewBuilder,因此可以正常工作:
struct TopAndBottomView<Content>: View where Content: View {
let topContent: () -> Content
let bottomContent: (() -> Content)?
init(@ViewBuilder topContent: @escaping () -> Content, bottomContent: (() -> Content)?) {
self.topContent = topContent
self.bottomContent = bottomContent
}
var body: some View {
VStack {
topContent()
Spacer()
if bottomContent != nil {
bottomContent!()
}
}
}
}
考虑到buildIf
的ViewBuilder
特性,可以采用以下方法将ViewBuilder
保留在[C0]中(最好)
经过测试并与Xcode 11.2 / iOS 13.2配合使用
init
如此工作)>
struct TopAndBottomView<Content>: View where Content: View { let topContent: () -> Content let bottomContent: () -> Content? init(@ViewBuilder topContent: @escaping () -> Content, @ViewBuilder bottomContent: @escaping () -> Content? = { nil }) { self.topContent = topContent self.bottomContent = bottomContent } var body: some View { VStack { topContent() Spacer() bottomContent() } } }
和这一个
struct TopAndBottomView_Previews: PreviewProvider {
static var previews: some View {
TopAndBottomView(topContent: {
Text("TOP")
}, bottomContent: {
Text("BOTTOM")
})
}
}