处理 SwiftUI 视图中的可选值/nil 值 - 在 SwiftUI 中使用 if let [重复]

2024-06-19

视图通常不允许可选参数值,从而导致类似的错误Initializer 'init(_:)' requires that 'String?' conform to 'StringProtocol':

struct Person {
    var name : String
}

struct OptionalsExampleView: View {

    var person : Person? = Person(name: "Bob")

    var body: some View {
        VStack() {
            Text("Name:")
            Text(person?.name)
        }

    }
}

不幸的是,从 Xcode 11.4/iOS 13 开始if letView Builder 块中不允许使用语句,从而导致类似的错误Closure containing control flow statement cannot be used with function builder 'ViewBuilder':

struct OptionalsExampleView: View {

    var person : Person? = Person(name: "Bob")

    var body: some View {
        VStack() {
            if let person = person { // <-- not allowed
                Text("Name:")
                Text(person?.name)
            }
        }

    }
}

(我知道这个问题已经被回答和问过很多次了。我自己写了这个问题并回答了它,以便有一篇比现有文章更简洁的简短概述文章,以便我可以在出现这个问题的地方链接到它向上)。


a) 在非常简单的情况下,使用可选的后备或带有强制解包的 if 检查(if在 View Builder 块中允许):

struct OptionalsExampleView: View {

    var person : Person? = Person(name: "Bob")

    var body: some View {
        VStack() {
            Text(person?.name ?? "")
            if person != nil {
                Text("Name:")
                Text(person!.name)
            }
        }
    }
}

b) Use Optional#map如果存在单个可选值,则显示单个视图:

struct OptionalsMapExampleView: View {

    var person : Person? = Person(name: "Bob")

    var body: some View {
        VStack() {
            person.map { person in
                VStack {
                    Text("Name:")
                    Text(person.name)
                }
            }
        }
    }

}

c) 包裹if let具有显式返回类型的组视图中的块。if let如果它是视图生成器块中的唯一语句,则此处允许。如果块可以返回不同的视图类型,则视图需要包装为AnyView:

struct OptionalsGroupExampleView: View {

    var person: Person? = Person(name: "Bob")

    var body: some View {
        VStack {
            Group { () -> AnyView in
                if let person = person {
                    return AnyView(VStack {
                        Text("Name:")
                        Text(person.name)
                    })
                } else {
                    return AnyView(EmptyView())
                }
            }
        }
    }

}

d) 将逻辑提取到一个单独的函数中 -if let此处允许,因为它位于视图构建器块之外。如果函数可以返回不同的视图类型,则需要将视图包装为AnyView:

struct OptionalsFuncExampleView: View {

    var person : Person? = Person(name: "Bob")

    var body: some View {
        VStack() {
            personView()
        }
    }

    func personView() -> some View {
        if let person = person {
            return AnyView(
                VStack {
                    Text("Name:")
                    Text(person.name)
                }
            )
        } else {
            return AnyView(EmptyView())
        }
    }

}

e) 使用封装 if-let 条件的辅助 View 类型,示例实现:IfLet https://stackoverflow.com/a/60203901/128083 / OptionalView https://medium.com/@garsdle/unwrapping-optionals-in-swiftui-7563dcc200e7;也可用作函数ifLet https://stackoverflow.com/questions/60223711/how-to-set-default-clouse-param-in-view-method/60225784#60225784.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

处理 SwiftUI 视图中的可选值/nil 值 - 在 SwiftUI 中使用 if let [重复] 的相关文章

随机推荐