SwiftUI直通车系列(4)—— 处理用户交互

SwiftUI直通车系列(4)—— 处理用户交互

前情回顾:

SwiftUI直通车系列(1)—— 视图的布局与组织

SwiftUI直通车系列(2)—— 列表视图

SwiftUI直通车系列(3)—— 使用导航

前面,我们介绍了在SwiftUI中布局与页面跳转的相关逻辑,其中页面跳转可以算是处理用户交互,SwiftUI虽然从名字上听,是一个UI框架,但是其依然有很强大的交互处理能力。本篇博客,我们就其用户交互能力进行介绍和学习。

一、SwiftUI中的按钮

    按钮是处理用户交互的最基础的组件,在SwiftUI中,使用Button可以十分方便的定义按钮组件,如下:

1var count = 0 2struct SimpleView:View { 3 4 var body: some View { 5 VStack(alignment: .center, spacing: 20) { 6 Button(action:{ 7 count += 1 8 }){ 9 Text("按钮一") 10 } 11 Text("\(count)") 12 } 13 } 14} 15 16struct ContentView_Previews: PreviewProvider { 17 static var previews: some View { 18 SimpleView() 19 } 20}

在预览界面,可以看到一个按钮和计数器已经布局在了页面上,我们尝试点击按钮,会发现变量count虽然已经被改变了,但是页面并没有更新。能够接收到用户交互只是第一步,在SwiftUI中通过用户交互而进行页面的刷新才是核心我们需要关注的。效果如下:

二、状态

    SwiftUI采用的是描述性的结构化布局策略,即通过定义结构体这种结构化的数据来描述页面的布局。这种布局思路开发直观快速,并且非常易于入门上手。其与流行的前端框架Flutter,React等布局思路已经非常相似。因此,对于页面的刷新操作,我们也不能采用原始的iOS开发页面刷新的方式(对对象进行操作),而是要使用状态来对组件进行管理,改变组件的状态来实现组件刷新操作。

    修改上面代码如下:

1struct SimpleView:View { 2 @State var count = 0 3 var body: some View { 4 VStack(alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/, spacing: 20) { 5 Button(action:{ 6 self.count += 1 7 }){ 8 Text("按钮一") 9 } 10 Text("\(self.count)") 11 } 12 } 13} 14 15struct ContentView_Previews: PreviewProvider { 16 static var previews: some View { 17 SimpleView() 18 } 19}

重新恢复预览,可以看到计数器的功能已经正常了。@State是SwiftUI中提供的一个属性装饰器,其可以将某个属性指定为有状态的,当有状态的属性发生变化时,与其绑定的组件会自动刷新。

    如果有状态属性在父组件中,而我们需要在子组件中处理用户交互逻辑进行页面刷新,这时,如果不做特殊的处理,子组件会因为结构体不可修改的原则而导致无法对传递进来的状态属性进行更改。对于这种场景,我们可以使用SwiftUI中提供的@Binding装饰器来修改子组件中的属性,例如:

1struct SimpleSubText:View { 2 @Binding var count:Int 3 var body: some View { 4 Button(action:{ 5 self.count += 1 6 }){ 7 Text("按钮一") 8 } 9 Text("\(self.count)") 10 } 11} 12 13 14struct SimpleView:View { 15 @State var count = 0 16 var body: some View { 17 VStack(alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/, spacing: 20) { 18 SimpleSubText(count: $count) 19 } 20 } 21} 22 23struct ContentView_Previews: PreviewProvider { 24 static var previews: some View { 25 SimpleView() 26 } 27}

三、使用环境对象

    使用状态来管理组件刷新并不复杂,但是如果组件的嵌套层数较多,有状态数据的传递可能需要层层下传,这会使数据的流转变得相对复杂。在SwiftUI中,还有另外一种方式,可以定义环境对象,环境对象在SwiftUI组件的任意位置都可以自由访问和修改,与环境对象有绑定关系的组件都会接收到变动的通知并刷新。示例代码如下:

1// 作为环境数据的类,必须是可绑定监听的,需要继承ObservableObject 2class EnviData: ObservableObject { 3 @Published var count = 0 4} 5 6struct SimpleSubText:View { 7 // 获取环境数据进行使用 8 @EnvironmentObject var data:EnviData 9 var body: some View { 10 Button(action:{ 11 self.data.count += 1 12 }){ 13 Text("按钮一") 14 } 15 Text("\(self.data.count)") 16 } 17} 18 19 20struct SimpleView:View { 21 var body: some View { 22 VStack(alignment: .center, spacing: 20) { 23 SimpleSubText() 24 } 25 } 26} 27 28struct ContentView_Previews: PreviewProvider { 29 static var previews: some View { 30 // 传递环境数据 31 SimpleView().environmentObject(EnviData()) 32 } 33}

需要注意,并不是环境对象中所有的属性都会触发绑定和监听,只有使用@published的属性才会触发,因此环境对象也是支持静态的内部属性。

专注技术,热爱生活,交流技术,也做朋友。

——珲少 QQ群:805263726

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

java将前端的json数组字符串转换为列表

记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang

SwiftUI直通车系列(3)—— 使用导航

SwiftUI直通车系列三(3)——使用导航  关于SwiftUI,我们前两篇博客介绍了独立组件的布局与属性设置相关内容,并且介绍了开发中最常用的列表视图的使用。但是一个完整的应用程序不可能是单界面的,如何使用SwiftUI进行界面间的导航跳转,是我们本博客讨论的重点。前两篇博客地址如下:Swi

SwiftUI直通车系列(1)—— 视图的布局与组织

SwiftUI直通车系列(1)——视图的布局与组织一、引言    SwiftUI提供了一种更快、更高效也更简单的页面开发方式。我们知道相对于ObjectiveC,Swift语言本身就更加高效简洁,SwiftUI采用了结构化的布局方式,使得应用的界面开发更加直观快速。本系列博客,