在SwiftUI中是否可以有一个可选的@ViewBuilder闭包?例如,假设我要开发一个自定义 View ,该 View 需要两个这样的 View 构建器闭包:

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")
        })
    }
}

但是我希望底 View 是可选的。我尝试了:
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!()
            }
        }
    }
}

但是我得到这个错误:



谢谢。

最佳答案

考虑到buildIfViewBuilder功能,可以采用以下方法将ViewBuilder保留在init中(最好)

经过测试并与Xcode 11.2/iOS 13.2配合使用

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")
        })
    }
}

还有这个
struct TopAndBottomView_Previews: PreviewProvider {
    static var previews: some View {
        TopAndBottomView(topContent: {
            Text("TOP")
        })
    }
}

10-07 23:42