SwiftUI如何修改页面状态?@state的使用

2023-05-16

在SwiftUI开发中流传一种说法:视图是状态的函数。这句话什么意思呢?

我们在玩游戏的时候,死了几次,得到几分,收集了一些道具,或者捡到武器,在应用程序中,我们把这些称为state。当你退出游戏的时候状态都会保存,当你下次再进来游戏的时候可以接着上次的继续玩。不过在你玩的过程中,这些所有的东西都可以叫状态:所有的integers,strings,booleans等等,这些存储在内存中的值描述着你现在在干嘛。

回到开头的疑问,我们说SwiftUI的视图们是状态的函数,其实意思是说,页面呈现给我们的样子都由程序的状态来决定,不管是能看到的,还是可以进行交互的内容。比如只有在输入框中填入了内容,我们才能继续进行下一步。而在传统的观念中:用户界面是由一系列事件决定的。我们现在能看到当前页面,是因为我们使用app过程中,点击了某些地方,或者登录了应用,刷新了数据等等。

如何修改状态?

说了这么多,那在SwiftUI中我们应该如何处理状态呢?我们先以一个按钮的例子开始:

struct ContentView: View {
    var tapCount = 0

    var body: some View {
        Button("Tap Count: \(tapCount)") {
            self.tapCount += 1
        }
    }
}

假如有上面的一个按钮,它有一个title,以及一个action,在按钮点击的时候改变属性tapCount的值。是不是看起来很合理?

实际上上面的代码在swift中是会报错的。ContentView是一个struct,而我们知道结构体是不可变的,所以我们不能随意改变它的值。

在创建一个结构体的方法之后,如果想在方法中修改属性的值,我们需要添加mutating关键字,比如这样:

mutating func doSomeThing()

但是Swift不允许声明可修改的计算型属性,也就是说我们不能这样写:

mutating var body: some View

我们好像陷入了一个僵局:程序运行过程中,我们想改变属性的值,但是Swift的struct不允许这样的操作,那该咋办呢?

这个时候就到我们的主角闪亮登场了,Swift提供了一种特殊的解决方案:属性包装器。它们是一些特殊的关键字,我们可以放置在属性前面来给属性提供超能力!在上面存储状态的例子中,我们是可以使用SwiftUI中的@State属性包装器,像这样:

struct ContentView: View {
    @State var tapCount = 0

    var body: some View {
        Button("Tap Count: \(tapCount)") {
            self.tapCount += 1
        }
    }
}

一点小小的改变,我们的程序就可以成功编译运行了。@State使得我们可以超出struct本身的限制,动态修改属性的值。是不是感觉有点像作弊?哈哈。

有些同学可能就会想到,SwiftUI为什么不直接使用类来表示一个view呢?我们知道类中可以随意的修改属性的值。其实随着学习SwiftUI的深入你会发现,在声明式的SwiftUI中,创建和销毁stuct是很频繁的操作,如果换成类,那会严重影响到程序的性能。

小提示:在使用@State包装一个属性的时候,苹果推荐我们为属性加上private的访问权限,像这样:

@State private var tapCount = 0

状态双向绑定

@State属性包装器已经允许我们自由修改结构体,这样我们就能在程序发生变化的时候,更新我们的界面了。但上面做的还不够,大家有没有想过,如果一个输入框的输入内容改变了,存储输入内容的属性该如何更新呢?

这就需要讲到双向绑定了。我们希望在页面的UI发生变化的时候,对应的属性也能随之改变,真正做到”页面时状态的函数“。还是拿输入框来说,我们用一个属性绑定了输入框,这样输入框可以展示我们属性中的值,但同时当输入框的内容有任何改变的时候同时也更新我们的属性,这就是双向绑定!

在Swift中我们使用一个特殊符号来表示$,在属性前加上$就意味着会读取属性的值同时任何改变也会更新属性的值。比如像这样:

struct ContentView: View {
    @State private var name = ""

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

运行后输入你的名字,会看到输入框下面会出现Hello 你的名字,在Text中我们使用name而不是$name是因为这里是取值,并不需要双向绑定。所以请记住:看到属性前有$符号,就表明这是一个双向绑定,属性的值读的同时也会被改。

我们还可以给绑定属性添加动画包装,这样在属性值发生变化时页面的变动会有动画效果,比如下面的栗子,开关打开时,TextField会更平滑的出现:

Toggle(isOn: $addLoyaltyDetails.animation()) {
    Text("Add iDine loyalty card")
}

if addLoyaltyDetails {
    TextField("Enter your iDine ID", text: $loyaltyNumber)
}

自定义的双向绑定

SwiftUI允许我们使用Binding类型来自定义双向绑定,我们可以实现自定义的set和get实现。比如下面的代码:

struct ContentView: View {
    @State private var username = ""

    var body: some View {
    
        let binding = Binding(
            get: { self.username },
            set: { self.username = $0 }
        )

        return VStack {
            TextField("Enter your name", text: binding)
        }
    }
}

我们自定义了一个binding,并提供了自己的set和get,在使用的地方,可以看到在binding前面不需要添加$符号。

那自定义双向绑定的好处是什么呢?我们可以在自定义绑定的set和get中添加自己的逻辑,比如对数据的处理,或者先进行额外的操作,再进行set和get,这样的应用场景应该还是蛮多的。

欢迎关注公众号:iOS进化论,关注后回复“干货”,有福利哦!
iOS进化论
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SwiftUI如何修改页面状态?@state的使用 的相关文章

  • centos7.9离线安装mysql5.7

    前言 windows server2003服务器 xff0c 安装mysql提示需要net framework xff0c 费了半天劲装好了 xff0c 发现解压版redis无法启动 xff0c 换了个低版本也是无法安装 xff0c 服务器
  • vs2019-slicer编译问题记录

    3D Slicer编译过程问题记录 官网教程 xff1a https slicer readthedocs io en latest developer guide build instructions windows html 环境 CM
  • sudo npm command not found 问题解决

    这种情况通常是使用 npm 命令可以正常使用 xff0c 但使用sudo npm 命令便会报 command not found 这是什么原因呢 xff1f 输入which npm可以得到 usr local bin npm xff0c 这
  • (POJ1201)Intervals <差分约束系统-区间约束>

    Intervals Description You are given n closed integer intervals ai bi and n integers c1 cn Write a program that reads the
  • 【sv与c】sv与c交互

    网上此类文章很多 xff0c 这里暂时不放具体实现和测试结果 xff0c 后续持续更新 下面引用一些帖子 xff0c 帖子中涉及到具体做法 vcs联合编译v sv c 43 43 代码 sxlwzl的专栏 CSDN博客 1 xff0c 假设
  • stm32f103c8t6最小系统

    提示 xff1a 文章写完后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 文章目录 前言stm32f103c8t6构成二 xff1a 电源电路稳压模块注意 复位电路NRST 时钟电路程序下载电路JTAGSWD 启
  • udp中的connect()&bind()

    connect amp bind 的作用 udp udp connect span class hljs preprocessor include lt sys types h gt span span class hljs preproc
  • Linux Hook技术实践

    LInux Hook技术实践 什么是hook 简单的说就是别人本来是执行libA so里面的函数的 xff0c 结果现在被偷偷换成了执行你的libB so里面的代码 xff0c 是一种替换 为什么hook 恶意代码注入调用常用库函数时打lo
  • Tensorflow Cnn mnist 的一些细节

    Tensorflow cnn MNIST 笔记 写这个完全是记录看官网example时不懂 xff0c 但后来弄懂的一些细节 当然这个可以算是对官方文档的补充 xff0c 也许每个人遇到的不懂都不一样 xff0c 但希望对大家有帮助 先上代
  • effective cpp 读书笔记2

    当你用到多态时 xff0c 务必把析构函数做成虚函数 以前知道子类的析构函数会自动调用父类的析构函数 xff0c 然而今天却发现不总是这样 当你用基类的指针指向派生类时 xff0c 然后delete这个指针时 xff0c 有可能就不会调用派
  • malloc与缺页的一些的时间测量

    malloc与缺页的一些的时间测量 时间函数 span class hljs keyword struct span timespec time t tv sec span class hljs keyword long span span
  • N皇后问题的并行解法

    N皇后问题的并行解法 N皇后问题 其实就是一个n n的棋盘上摆n个皇后 xff0c 任意两个皇后不能同行 xff0c 同列 xff0c 同对角线 xff0c 求出所有的摆法 这个问题可以看做是求n的组合数 比如第一列上的皇后在第x1行 xf
  • apache服务器使用时网页乱码问题

    查看原文 xff1a http www hellonet8 com 440 html 在apache的配置文件httpd conf中 xff0c 或许我们会用到 AddDefaultCharset UTF 8 来设置所有主机或者某虚拟主机的
  • 将群晖NAS变为本地盘

    本文介绍一个工具 xff0c 可以在 Windows 系统下将群晖NAS的目录变为本地盘 xff0c 好处是在外部访问的时候 xff0c 能够大大改善体验 可以用本地的应用程序直接打开 xff0c 速度依赖网络带宽 xff0c 正常情况下
  • Deepin | 修改网卡名 | 配置IP地址 | DHCP

    文章目录 修改网卡名解决方案 xff1a 配置IP地址解决方案 xff1a DHCP自动获取 修改网卡名 解决方案 xff1a 禁用该可预测命名规则 span class token function sudo span vim etc d
  • windows商店直接安装ubuntu子系统

    文章目录 安装报错WslRegisterDistribution failed with error 0x8007019eWSL安装Linux报错WslRegisterDistribution failed with error 0x803
  • 基于VTK的任意平面切割

    这位 小兵 太传奇了 xff0c 先收藏 xff0c 再学习 xff0c http www cnblogs com dawnWind archive 2013 02 17 3D 06 html 先贴码 以后再 切割介绍 对于一个模型的切割需
  • 百度OCR接口使用

    最近在研究ocr识别 也对比了一些的方法 现在来介绍一下 调用百度提供的ocr接口 小量调用的话 是不收费的 1 首先 你要有一个百度账号 如果已经有的话 登录进去会进入到这样一个界面 点击 34 创建应用 34 创建成功后 返回应用列表
  • Python 元组(tuple)剖析详解

    目录 概念元组的常见操作 概念 元组 span class token punctuation span 是一个有序 span class token punctuation span 可重复的集合 特点 span class token
  • Dom型XSS跨站脚本攻击和防御

    在前面的文章中 xff0c 我们讲了持久型XSS和反射型XSS 我个人觉得这些命名真的很贴切 xff0c 反应了概念的本质 无论是持久型XSS还是反射型XSS 恶意的js脚本内容都需要由服务端返回给用户 xff0c 今天我们要说的Dom型X

随机推荐