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

Easter79
• 阅读 782

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

前情回顾:

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

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

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

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

一、SwiftUI中的按钮

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

var count = 0
struct SimpleView:View {
    
    var body: some View {
        VStack(alignment: .center, spacing: 20) {
            Button(action:{
                count += 1
            }){
                Text("按钮一")
            }
            Text("\(count)")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
       SimpleView()
    }
}

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

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

二、状态

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

    修改上面代码如下:

struct SimpleView:View {
    @State var count = 0
    var body: some View {
        VStack(alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/, spacing: 20) {
            Button(action:{
                self.count += 1
            }){
                Text("按钮一")
            }
            Text("\(self.count)")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
       SimpleView()
    }
}

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

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

struct SimpleSubText:View {
    @Binding var count:Int
    var body: some View {
        Button(action:{
            self.count += 1
        }){
            Text("按钮一")
        }
        Text("\(self.count)")
    }
}


struct SimpleView:View {
    @State var count = 0
    var body: some View {
        VStack(alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/, spacing: 20) {
            SimpleSubText(count: $count)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
       SimpleView()
    }
}

三、使用环境对象

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

// 作为环境数据的类,必须是可绑定监听的,需要继承ObservableObject
class EnviData: ObservableObject {
    @Published var count = 0
}

struct SimpleSubText:View {
    // 获取环境数据进行使用
    @EnvironmentObject var data:EnviData
    var body: some View {
        Button(action:{
            self.data.count += 1
        }){
            Text("按钮一")
        }
        Text("\(self.data.count)")
    }
}


struct SimpleView:View {
    var body: some View {
        VStack(alignment: .center, spacing: 20) {
            SimpleSubText()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        // 传递环境数据
        SimpleView().environmentObject(EnviData())
    }
}

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

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

——珲少 QQ群:805263726

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
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
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Easter79 Easter79
3年前
SwiftUI直通车系列(3)—— 使用导航
SwiftUI直通车系列三(3)——使用导航  关于SwiftUI,我们前两篇博客介绍了独立组件的布局与属性设置相关内容,并且介绍了开发中最常用的列表视图的使用。但是一个完整的应用程序不可能是单界面的,如何使用SwiftUI进行界面间的导航跳转,是我们本博客讨论的重点。前两篇博客地址如下:Swi
Easter79 Easter79
3年前
SwiftUI直通车系列(1)—— 视图的布局与组织
SwiftUI直通车系列(1)——视图的布局与组织一、引言    SwiftUI提供了一种更快、更高效也更简单的页面开发方式。我们知道相对于ObjectiveC,Swift语言本身就更加高效简洁,SwiftUI采用了结构化的布局方式,使得应用的界面开发更加直观快速。本系列博客,
Easter79 Easter79
3年前
SwiftUI直通车系列(5)—— 自定义绘制
SwiftUI直通车系列(5)——自定义绘制前情回顾:SwiftUI直通车系列(1)——视图的布局与组织(https://my.oschina.net/u/2340880/blog/4529951)SwiftUI直通车系列(2)——列表视图(https://my.oschina.net
Easter79 Easter79
3年前
SwiftUI直通车系列(6)—— 使用动画
SwiftUI直通车系列(6)——使用动画   本系列博客是针对SwiftUI开发框架的快速入门介绍,之前系列博客地址:SwiftUI直通车系列(1)——视图的布局与组织(https://my.oschina.net/u/2340880/blog/4529951)SwiftUI直通车系列
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Easter79 Easter79
3年前
SwiftUI直通车系列(2)—— 列表视图
SwiftUI直通车系列(2)——列表视图  列表视图的开发中非常常用的页面元素。SwiftUI中也有专门用来渲染列表的元素提供。一、编写行视图   列表实际上是一组行视图的组合,在布局列表视图之前,你首先需要定义好行视图的布局。例如,我们使用一个Image元素和两个Tex
Easter79 Easter79
3年前
SwiftUI 跨组件数据传递
作者:Cyandev,iOS和MacOS开发者,目前就职于字节跳动0x00前言众所周知,SwiftUI的开发模式与React、Flutter非常相似,即都是声明式UI,由数据驱动(产生)视图,视图也会与数据自动保持同步,框架层会帮你处理“绑定”的问题。在声明式UI中不存在命令式地让一个视图变成xxx
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k