可选的@ViewBuilder 闭包 [英] Optional @ViewBuilder closure

查看:26
本文介绍了可选的@ViewBuilder 闭包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 SwiftUI 中是否可以有一个可选的 @ViewBuilder 闭包?例如,假设我想开发一个自定义视图,它需要两个视图构建器闭包,如下所示:

Is it possible in SwiftUI to have an optional @ViewBuilder closure? For example, let's say I want to develop a custom view that takes two view builder closures like this:

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

但我希望底部视图是可选的.我试过:

But I'd like the bottom view to be optional. I tried with:

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"只能应用于函数类型参数.

Function builder attribute 'ViewBuilder' can only be applied to a parameter of function type.

谢谢.

推荐答案

考虑到 ViewBuilderbuildIf 特性,以下方法是可能的,允许保留 init 中的 ViewBuilder(最好)

Taking into account buildIf feature of ViewBuilder the following approach is possible that allows to keep ViewBuilder in init (that is preferable)

经过测试适用于 Xcode 11.2/iOS 13.2

Tested & works with 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")
        })
    }
}

这篇关于可选的@ViewBuilder 闭包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆