SwiftUI - 带有条件闭包的 if let 的替代方案

Vee*_*Vee 10 closures view optional conditional-statements swiftui

我正在尝试在 SwiftUI 中实现以下内容:

struct PersonView: View {

    @State private var age: Int? = 0

    var body: some View {
        VStack {
            Text("Just a test")
            if let self.age > 0 {
                Text("Display Age: \(age)")
            } else {
                Text("Age must be greater than 0!")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,在 SwiftUI 中,会if let导致以下错误:

包含控制流语句的闭包不能与函数构建器“ViewBuilder”一起使用

因此,在研究了这个主题之后,我遇到了一个.map用于解开age可选项的建议。因此,我已修改VStack为如下代码:

Text("Just a test")
self.age.map {elem in
    if elem > 0 {
        Text("Display Age: \(elem)")
    } else {
        Text("Age must be greater than 0!")
    }
}
Run Code Online (Sandbox Code Playgroud)

.map但是,在闭包中包含条件会导致调用 的行出现以下错误VStack

' (ViewBuilder.Type) -> (C0, C1) -> TupleView<(C0, C1)>' 要求 '()' 符合 'View'

类型 '()' 不符合协议 'View'

关于如何克服第二组错误的任何建议?或者,是否有另一种方法可以在 SwiftUI 中解开可选项并评估它们?真的很喜欢 SwiftUI,但不敢相信解包选项一直令人头疼!

Asp*_*eri 12

对于这种情况,我更喜欢以下方法

struct PersonView: View {

    @State private var age: Int? = 0

    var body: some View {
        VStack {
            Text("Just a test")
            AgeText
        }
    }

    private var AgeText: some View {
        if let age = self.age, age > 0 {
            return Text("Display Age: \(age)")
        } else {
            return Text("Age must be greater than 0!")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Moj*_*ini 6

斯威夫特 5.3 (Xcode 12)

现在您可以在视图构建器中使用条件绑定:

if let age = age {
    if age > 0 {
        Text("Display Age: \(age)")
    } else {
        Text("Age must be greater than 0!")
    }
} else {
    Text("Age not found")
}
Run Code Online (Sandbox Code Playgroud)

重构(也适用于较旧的 Swift)

您可以将代码重构为更基本的内容,例如使用函数:

var body: some View {
    VStack {
        Text("Just a test")
        Text(text(age: age)) // Using the function
    }
}

func text(age: Int?) -> String { // Defining the function
    guard let age = age else { return "Age not found" }
    if age > 0 { return "Display Age: \(age)" }
    else { return "Age must be greater than 0!" }
}
Run Code Online (Sandbox Code Playgroud)

通常,在需要清理代码的地方使用函数。我希望未来的 Swift 版本会像我们期望的那样直接支持这一点。


LuL*_*aGa 6

您正在尝试对 age 的值进行两次检查:首先确保它不是nil,然后检查它是否大于 0。您可以使用 map 来消除潜在的nil,然后使用三元运算符有条件地更改文本显示:

var body: some View {
    VStack {
        Text("Just a test")
        age.map { Text( $0 > 0 ? "Display Age: \($0)" : "Age must be greater than 0!") }
    }
}
Run Code Online (Sandbox Code Playgroud)