SwiftU:将状态绑定到UI控件

2020-03-20 12:24:51 浏览数 (1)

SwiftUI的@State属性包装器允许我们自由修改视图结构体,这意味着当程序更改时,我们可以更新视图属性以匹配。

但是,使用UI控件时,事情会更复杂一些。例如,如果要创建用户可以键入的可编辑文本框,可以创建如下所示的快速用户界面视图:

代码语言:javascript复制
struct ContentView: View {
    var body: some View {
        Form {
            TextField("Enter your name")
            Text("Hello World")
        }
    }
}

尝试创建包含文本字段和文本视图的窗体。但是,该代码不会编译,因为SwiftUI想知道文本字段中的文本存储位置。

请记住,视图是其状态的函数——文本输入框只能在反映存储在程序中的值时显示某些内容。SwiftUI需要的是结构中的一个字符串属性,它可以显示在文本输入框中,还将存储用户在文本输入框中键入的任何内容。

所以,我们可以把代码改成:

代码语言:javascript复制
struct ContentView: View {
    var name = ""

    var body: some View {
        Form {
            TextField("Enter your name", text: name)
            Text("Hello World")
        }
    }
}

这将添加一个name属性,然后使用它创建文本字段。但是,该代码仍然无法工作,因为Swift需要能够更新name属性以匹配用户在文本字段中键入的任何内容,因此您可以使用`@State``,如下所示:

代码语言:javascript复制
@State private var name = ""

但这还不够,我们的代码仍然无法编译。

问题是Swift区分了“在此处显示此属性的值”和“在此处显示此属性的值,但将任何更改写回该属性”

在Swift中,我们用一个特殊的符号来标记这些双向绑定,这样它们就很显眼:我们在它们前面写一个美元符号$。这告诉Swift,它应该读取属性的值,但也应该在发生任何更改时将其写回。

所以,我们的结构体的正确版本是:

代码语言:javascript复制
struct ContentView: View {
    @State private var name = ""

    var body: some View {
        Form {
            TextField("Enter your name", text: $name)
            Text("Hello World")
        }
    }
}

现在试着运行这个代码——你应该发现你可以点击文本字段并输入你的名字,如预期的那样。

在继续之前,让我们修改文本视图,使其在文本字段的正下方显示用户名:

代码语言:javascript复制
Text("Your name is (name)")

注意它是如何使用name而不是$name?这是因为我们不想在这里使用双向绑定——我们想读取值,是的,但我们不想以某种方式将其写回,因为文本视图不会改变。

因此,当您在属性名称前看到一个美元符号时,请记住它创建了一个双向绑定:属性的值是读的,也是写的。

Binding state to user interface controls

0 人点赞