SwiftUI 入门趣谈:在文本框(TextField)内限制数字的输入

news2024/12/27 14:16:08

在这里插入图片描述

概述

虽然 SwiftUI 本身提供了海量内置的原生视图供我们使用,但对于某些情况我们还需要根据实际需求“量体裁衣、专属定制”。

在这里插入图片描述

在日常的撸码场景中,我们有时需要限制文本框(TextField)中数字内容的输入,如何又简单又快速的实现它呢?

在本篇博文中,您将学到如下内容:

  • 概述
  • 1. 一个简单的“栗子”
  • 2. 在 Binding 外部监听并限制
  • 3. 拯救者:格式器(Formatter)
  • 总结

闲言少叙,让我们马上开始行动吧!Let‘s go!!!😉


1. 一个简单的“栗子”

我们的实现非常简单:将 TextField 中输入数字的大小限制在 0-9999 之间。

先上代码:

struct ContentView: View {
    
    @State var value = 0
    
    var body: some View {
        
        VStack {
            
            Text("\(value)")
                .font(.largeTitle.bold())
            
            TextField("输入 0-9999 之间的数字", text: .init {
                "\(value)"
            } set: { newString in
                guard let newValue = Int(newString) else { return }
                value = min(9999, max(0, newValue))
            })
            .keyboardType(.decimalPad)
            .textFieldStyle(.roundedBorder)
        }
        .padding()
    }
}

在上面的代码中,我们利用一个自定义绑定(Binding)实现了目标数值的约束。可以看到,在绑定的 set 方法中我们将 value 限制在 0 - 9999 之间。

运行代码,看一下结果:

在这里插入图片描述

从结果可见:虽然最终输入值 value 被成功限制在了 0-9999 之间,但输入框(TextField)的输入内容并没有被限制住,这可不是我们想要的结果。看来在自定义绑定 set 方法中对 value 值的限定并没有让输入框本身的内容及时得到刷新。

这该如何是好呢?

2. 在 Binding 外部监听并限制

为了解决这一问题,我们需要在外部而不是绑定内部限制输入值。一种方法是利用 onChange() 修改器来监听并实施真正的约束:

struct ContentView: View {
    
    @State var value = 0
    
    var body: some View {
        NavigationStack {
            VStack {
                
                Text("\(value)")
                    .font(.largeTitle.bold())
                
                TextField("输入 0-9999 之间的数字", text: .init {
                    "\(value)"
                } set: { newString in
                    guard let newValue = Int(newString) else { return }
                    value = newValue
                })
                .keyboardType(.decimalPad)
                .textFieldStyle(.roundedBorder)
                .onChange(of: value) {_, new in
                    value = min(9999, max(0, new))
                }
            }
            .padding()
            .navigationTitle("限制输入数值演示")
            .toolbar {
                Text("大熊猫侯佩 @ \(Text("CSDN").foregroundStyle(.red))")
                    .foregroundStyle(.gray)
                    .font(.headline.bold())
            }
        }
    }
}

从上面代码可以看到,我们将原来 Binding 中对 value 值的限制逻辑“抽出来”放到了绑定外部的 onChange() 修改器中。这使得对 value 的更改会反过来引起输入框的重绘:

在这里插入图片描述

这样一来,我们就达到了限制 TextField 本身输入的效果,棒棒哒!💯

3. 拯救者:格式器(Formatter)

其实除了上面这种方法以外,我们还可以利用 TextField 自身提供的另一个构造器彻底“甩掉”自定义绑定来达到同样的效果:

在这里插入图片描述

不同于 TextField 默认的 构造器,这个构造器可以直接传入任意类型的绑定,只要它能被最后一个传入的格式器所转换(为 String)即可。

在这里插入图片描述

这意味着任何 Formatter 类的派生类都可以当做格式器传入进来。为什么能这样呢?这是因为 Formatter 类中有一个 string(for:) 方法可以将其它值转换为所需的字符串:

在这里插入图片描述

注意:如果 string(for:) 方法不能顺利完成转换(返回为nil),则 TextField 中的内容将保持不变。

于是乎,我们可以这样重构之前的代码了:

struct ContentView: View {
    @State var value = 0
    
    var body: some View {
        NavigationStack {
            VStack {
                Text("\(value)")
                    .font(.largeTitle.bold())
                
                TextField("输入 0-9999 之间的数字", value: $value, formatter: NumberFormatter())
                    .keyboardType(.decimalPad)
                    .textFieldStyle(.roundedBorder)
                    .onChange(of: value) {_, new in
                        value = min(9999, max(0, new))
                    }
            }
            .padding()
            .navigationTitle("限制输入数值演示")
            .toolbar {
                Text("大熊猫侯佩 @ \(Text("CSDN").foregroundStyle(.red))")
                    .foregroundStyle(.gray)
                    .font(.headline.bold())
            }
        }
    }
}

如您所见,在上面新的实现中我们使用系统内置的 NumberFormatter 格式化器完成了整型数值到字符串的转换:

在这里插入图片描述
在这里插入图片描述

编译并运行代码可以发现,结果和之前毫无二致,只不过逻辑变得更简单了:

在这里插入图片描述

现在,我们成功的对 TextField 的输入内容做了所需的限制,小伙伴们赶快给自己一个大大的赞吧!么么哒!


想要进一步系统地学习 Swift 开发的小伙伴们,可以来我的《Swift 语言开发精讲》专栏逛一逛哦:

在这里插入图片描述

  • 《Swift 语言开发精讲》

总结

在本篇博文中,我们讨论了在 SwiftUI 中如何限制文本框(TextField)中数字内容的输入。我们稍后用两种方法解决了问题,任君选择。

感谢观赏,再会了!😎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2266433.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入浅出 MyBatis | CRUD 操作、配置解析

3、CRUD 3.1 namespace namespace 中的包名要和 Dao/Mapper 接口的包名一致! 比如将 UserDao 改名为 UserMapper 运行发现抱错,这是因为 UserMapper.xml 中没有同步更改 namespace 成功运行 给出 UserMapper 中的所有接口,接下来一一对…

基于c语言的union、字符串、格式化输入输出

结构体之共用体union 共用体也叫联合体,其关键词为union 与结构体不同的是,共用体所开辟的存储空间仅仅为其中最长类型变量的存储空间而不是全部变量的存储空间,由于同一内存单元在同一时间内只能存放其中一种的数据类型,因此在每…

IntelliJ Idea常用快捷键详解

文章目录 IntelliJ Idea常用快捷键详解一、引言二、文本编辑与导航1、文本编辑2、代码折叠与展开 三、运行和调试四、代码编辑1、代码补全 五、重构与优化1、重构 六、使用示例代码注释示例代码补全示例 七、总结 IntelliJ Idea常用快捷键详解 一、引言 在Java开发中&#xff…

AI开发:使用支持向量机(SVM)进行文本情感分析训练 - Python

支持向量机是AI开发中最常见的一种算法。之前我们已经一起初步了解了它的概念和应用,今天我们用它来进行一次文本情感分析训练。 一、概念温习 支持向量机(SVM)是一种监督学习算法,广泛用于分类和回归问题。 它的核心思想是通过…

Linux-----进程处理(子进程创建)

【尚硅谷嵌入式Linux应用层开发,linux网络编程,linux进程线程,linux文件io】https://www.bilibili.com/video/BV1DJ4m1M77z?p35&vd_source342079de7c07f82982956aad8662b467 main函数 fork创建进程 fork()参数 /*** brief 创建一个子进…

一种寻路的应用

应用背景 利用长途车进行货物转运的寻路计算。例如从深圳到大连。可以走有很多条长途车的路线。需要根据需求计算出最合适路线。不同的路线的总里程数、总价、需要的时间不一样。客户根据需求进行选择。主要有一些细节: 全国的长途车车站的数据的更新: …

2. FPGA基础了解--全局网络

前言 引入扇出的概念介绍FPGA中的全局网络为后续时序优化埋下伏笔 扇出 在FPGA设计中扇出是一个重要的概念,所谓的扇出就是一个控制信号所能控制的数据信号的总个数,比如ctrl信号的扇出就是16 reg ctrl 0; reg [15:0] out 0; always (posedge c…

Excel中一次查询返回多列

使用Excel或wps的时候,有时候需要一次查询返回多列内容,这种情况可以选择多次vlookup或者多次xlookup,但是这种做法费时费力不说,效率还有些低下,特别是要查询的列数过多时。我放了3种查询方法,效果图&…

智能化军事【五】精确制导武器智能化实现

文章目录 前言精确制导武器智能化实现基于深度学习实现的智能化功能基于强化学习实现的智能化功能强化学习深度强化学习 网络模型轻量化网络剪枝(通道剪枝)技术层剪枝权值量化技术低秩近似技术知识蒸馏技术强化学习联合训练 解决有效训练样本不足或获取困…

解锁高效密码:适当休息,让学习状态满格

一、“肝帝” 的困境 在当今竞争激烈的职场中,“肝帝” 现象屡见不鲜。超长工时仿佛成为了许多行业的 “标配”,从互联网企业的 “996”“007”,到传统制造业的轮班倒、无休无止的加班,员工们的工作时间被不断拉长。清晨&#xff…

asp.net 高校学生勤工俭学系统设计与实现

博主介绍:专注于Java(springboot ssm 等开发框架) vue .net php python(flask Django) 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设,从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找…

WebRTC服务质量(12)- Pacer机制(04) 向Pacer中插入数据

WebRTC服务质量(01)- Qos概述 WebRTC服务质量(02)- RTP协议 WebRTC服务质量(03)- RTCP协议 WebRTC服务质量(04)- 重传机制(01) RTX NACK概述 WebRTC服务质量(…

RTMW:实时多人2D和3D 全人体姿态估计

单位:上海AI实验室 代码:mmpose/tree/main/projects/rtmpose 系列文章目录 RTMO: 面向高性能单阶段的实时多人姿态估计 目录 系列文章目录摘要一、背景二、相关工作2.1 自上而下的方法。2.2 坐标分类。2.3 3D Pose 3 实验方法3.1.1 任务限制3.1.3训练技…

AI智能养站神器-SEO助理原创文章批量生成发布工具

很多站长最头疼的就是网站每天的内容更新,因为不知道写什么,采集被人的文章又会被定义为抄袭,而且现在伪原创已经没有多大的效果了,所以今天给大家分享的就是一款AI智能养战神器-SEO助理原创文章批量生成发布工具。 这款工具支持…

用Python开启人工智能之旅(三)常用的机器学习算法与实现

第三部分:常用的机器学习算法与实现 用Python开启人工智能之旅(一)Python简介与安装 用Python开启人工智能之旅(二)Python基础 用Python开启人工智能之旅(三)常用的机器学习算法与实现 用Pyt…

FD(File Descriptor)泄漏

File Descriptor是Linux下概念,fd 是 int类型非负数! 进程打开File,Socket,Pipe后生成一个File Descriptor,它是打开这个系统资源的标识符。 Linux每个进程fd最大1024个,超过之后进程 crash,c…

英语单词拼读小程序开发制作介绍

英语单词拼读小程序开发制作介绍本英语单词拼读小程序系统开发的主要功能有: 1、按年级分类展示每个年级阶段的英语单词信息。 2、点击选择的单词进入单词拼读页面,展示英语单词的拼读音标、中文意思、单词发音、拆分词汇发音、用户通过朗读发音对比。通…

TCP客户端模拟链接websocket服务端发送消息(二)

兄弟们,我来填坑了,o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o,前几天写了个tcp模拟websocket客户端的以为完成,后面需要发送消息给服务端,以为简单不就是一个发送消息么,这不是一…

Docker 镜像加速访问方案

在数字化时代,Docker以其轻量级和便捷性成为开发者和运维人员的首选容器技术。然而自2023年5月中旬起,Docker Hub 的访问速度较慢或不稳定,这对依赖Docker Hub拉取镜像的用户来说无疑是一个挑战。本文将提供 Docker Hub 访问的一系列替代方案…

牛客网刷题 ——C语言初阶——BC112小乐乐求和

1.牛客网刷题 ——C语言初阶 牛客网:BC112小乐乐求和 小乐乐最近接触了求和符号Σ,他想计算的结果。但是小乐乐很笨,请你帮助他解答。 输入描述: 输入一个正整数n (1 ≤ n ≤ 109) 输出描述: 输出一个值,为求和结果。 示例1 输…