状态
在上一章,我们介绍了SwiftUI的主要特性,声明式语法。借助SwiftUI,我们可以按希望在屏幕上显示的方式声明视图,余下交由系统来创建所需的代码。但声明式语法不只用于组织视图,还可在应用状态发生变化时更新视图。例如,我们可以有下面图6-1中的界面,显示标题的Text视图,用户输入新标题的输入字段以及将旧标题替换成新标题的按钮。原标题的Text视图表示我们界面的初始状态。用户在输入框中输入每个字符时状态都会发生更新(图6-1左图),点击按钮时,界面进入一个新状态,用户插入的标题会替换原标题,文本的颜色也发生变化(图6-1右图)。

图6-1:用户界面
每次状态发生改变时,必须更新视图来进行反馈。在之前的系统中,这要求代码保持数据及界面同步,但在声明式语法中我们只需要声明每个状态的视图配置,系统会负责生成在屏幕上显示这些改变所需的代码。
界面可能经历的状态由存储在应用中的信息决定。例如,用户在输入框架中插入的字符以及示例中使用的颜色都是存储在应用中的值。每当这些值发生改变时,应用都会进入新状态,因此界面会发生更新进行反馈。建立应用数据与界面之间的依赖需要大量的代码,但SwiftUI通过属性包装器让其保持简单。
@State
在第3章中讨论过,属性包装器让我们可以定义用赋给它们的值定义可执行任务的属性。SwiftUI实现了大量的属性包装器来存储值并向视图上报修改。设计用于存储单个视图状态的名为@State。这个属性包装器将值存储在类型为State的结构体中,并在值发生改变时通知系统,这样视图会自动更新来在屏幕中进行反映。
属性包装器@State是设计用于存储单个视图的状态的。因此,我们应将这个类型的属性声明为视图结构体的一部分,并使用private,这样访问就可以限定在所声明的结构体内了。
示例6-1:定义一个状态
struct ContentView: View {
@State private var title: String = "Default Title"
var body: some View {
VStack {
Text(title)
.padding(10)
Button(action: {
title = "My New Title"
}, label: {
Text("Change Title")
})
Spacer()
}.padding()
}
}
示例6-1中的代码声明了一个String类型名为title的@State属性。该属性使用"Default Title"值进行初始化。在视图内容中,我们在垂直堆叠中以Text视图显示这个值,并在其下放了一个Button视图来修改其值。稍后我们会学习Button视图,但现在读者只需要知道Button视图显示一个标签并在用户点击按钮时操作一个操作。为展示标签,我们使用带"Change Title"文本的Text视图来让用户知道按钮的作用,并定义好操作,我们提供一个闭包修改title属性的值为"My New Title",这样在点击按钮时标题就会发生修改。
使用@State包装器创建的title属性在两个地方用到了,第一个是向用户显示当前值的Text视图,第二是Button视图中修改其值的操作。因此,每交点击按钮时,title属性的值会发生改变化,@State属性包装器通知系统应用的状态发生的变化,body属性的内容自动刷新在屏幕上显示新值。

图6-2:初始状态(左)和点击按钮后的状态(右)
✍️跟我一起做:创建一个多平台项目。使用示例6-1中的代码更新ContentView视图。确保对画布启用了实时预览(图5-18,1号图)。点击Change Title按钮将字符串赋值给Text视图。会看到像图6-2右图中的效果。
整个过程是自动完成的。我们不用对Text视图赋新值或是告诉该视图新的值,这一切都由@State属性包装器处理。我们可以包含多个存储界面状态的@State属性。例如,下例中我们对视图添加了一个Bool类型的@State属性,在每次点击按钮时为title属性赋不同的文本。
示例6-2:定义多个状态
st

本文详细介绍了SwiftUI中的声明式语法如何处理应用状态变化,包括使用@State属性存储视图状态,@Binding实现双向绑定,以及如何通过属性包装器简化状态与界面的同步。通过实例展示了如何创建和更新视图以反映状态变化,并探讨了不同绑定方法的使用和应用场景。
最低0.47元/天 解锁文章
493

被折叠的 条评论
为什么被折叠?



