可选的@ViewBuilder闭包

问题描述 投票:1回答:2

在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'只能应用于函数类型的参数。

谢谢。

ios swift swiftui
2个回答
0
投票

似乎您在初始化程序中不需要@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!()
            }
        }
    }
}

0
投票

考虑到buildIfViewBuilder特性,可以采用以下方法将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")
        })
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.