SwiftUI数据流与界面绑定

Posted liuxiaokun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SwiftUI数据流与界面绑定相关的知识,希望对你有一定的参考价值。

SwiftUI 中引入了一个关键字 @State 来作为数据绑定的标识。当一个被绑定的数据被改变时,相关联的视图会重新计算它自己的 body 内容;反过来,当视图主动去改变绑定在数据上的属性时,这个数据也会随之变化

SwiftUI 的数据流模型是基于下面两点原则来构建的:

Data Access as a Dependency:以依赖的形式访问数据 Source of Truth:单一数据源

展开来看: Data Access as a Dependency 在多数情况下,我们的视图是需要根据某些状态来动态变化显示样式的,比如对于 Switch 来说,改变它的 on 属性可以让它显示当前的开关状态。

对于这种情况,on 属性就应该作为 Switch 的依赖而存在,否则这个控件除了长得好看就一无是处了。所以在 SwiftUI 里,属性会被描述为视图的依赖,这意味着我们的注意力可以从属性和视图的关联里抽身出来,集中在建立更好的用户体验上。

Source of Truth 同一组视图里的数据都是来自于同一个数据源的

使用 @State 标记的变量会自动生成一个以 $ 作为前缀的新变量,这个新变量本质上是一个 Computed Value,实现了双向绑定的机制

通过声明变量为 @Binding,我们就告诉了编译器这个变量是从外部传入的可以被绑定的参数,相当于 React 里的 Props 声明

变量的声明和使用都是在一个结构体里面完成的,这就意味着这个视图与 视图 是解偶的

 

SwiftUI数据流温故知新 - 属性包装

@State

@State属性允许修改Struct的属性,这些属性在普通的Struct里面是不允许修改的。当把@State放置到属性前,该属性实际上会被放到Struct的外部存储起来,这意味着SwiftUI能够随时销毁和重建Struct而不会丢失属性的值。

@State包装的属性通常是设置成私有的,不让外部使用。如果想让外部使用,则应该使用@ObservedObject和@EnvironmentObject,他们能够使外部修改属性后,状态能够得到改变。

建议把@State包装的属性都设置成私有

@Published

@Published是SwiftUI最有用的包装之一,允许我们创建出能够被自动观察的对象属性,SwiftUI会自动监视这个属性,一旦发生了改变,会自动修改与该属性绑定的界面。

1.首先需要遵循ObservableObject属性

class Bag: ObservableObject { var items = [String]() }

2.包装属性

class Bag: ObservableObject { @Published var items = [String]() }

这样就完成了。@Published包装会自动添加willSet方法监视属性的改变。

@ObservedObject

@ObservedObject告诉SwiftUI,这个对象是可以被观察的,里面含有被@Published包装了的属性。

@ObservedObject包装的对象,必须遵循ObservableObject协议。也就是说必须是class对象,不能是struct。

@ObservedObject允许外部进行访问和修改。

@EnvironmentObject

@EnvironmentObject包装的属性是全局的,整个app都可以访问

需要注意的是,不需要给定默认值,由于该属性是整个app都可以访问的,SwiftUI会自动的从环境中取出来。

当****有这样一个场景,A->B->C->D->E->F,A界面的数据要传递给F界面,假如使用@ObservedObject包装,则需要一层一层传递,而使用@EnvironmentObject则不需要,直接在F界面,通过SwiftUI环境直接取出来就行。

需要注意的是,当界面显示时,就会去环境中取,但是,假如之前没有把属性放到环境中,则程序会崩溃。

@Environment

@Environment与@EnvironmentObject作用是不同的,@Environment是从环境中取出预定义的值,比如获得当前是暗黑模式还是正常模式,屏幕的大小等等。

@Environment(.horizontalSizeClass) var horizontalSizeClass
@Environment(.managedObjectContext) var managedObjectContext

@Binding

@Binding也是非常重要的一个包装,声明一个属性是从外部获取的,并且与外部是共享的。相当于外部传过来的时候,不是传递的值。任何一方修改都会让SwiftUI的监视生效。

@GestureState

@GestureState能够让我们传递手势的状态,虽然使用@State也能实现,但@GestureState能让手势结束后我们回到最初的状态。

设置属性,设置zero意味着手势结束后,会回到最初的值。

以上是关于SwiftUI数据流与界面绑定的主要内容,如果未能解决你的问题,请参考以下文章

一行代码为特定状态绑定SwiftUI视图动画

一行代码为特定状态绑定SwiftUI视图动画

SwiftUI - 绑定到选择器的变量与选择器的选定值不匹配

实用代码片段将json数据绑定到html元素 (转)

如何在 SwiftUI 中使用枚举绑定数据?

如何在 SwiftUI 的视图控制器中实现数据绑定?