我是 SwiftUI 和 iOS 的新手,我正在尝试创建一个仅接受数字的输入字段。
TextField("Total number of people", text: $numOfPeople)
The TextField
目前允许输入字母字符,如何让用户只能输入数字?
尽管显示数字键盘是一个很好的第一步,但它实际上并不能防止输入错误数据:
- 用户可以将非数字文本粘贴到
TextField
- iPad 用户仍将获得全键盘
- 连接蓝牙键盘的任何人都可以输入任何内容
你真正想做的是清理输入,如下所示:
import SwiftUI
import Combine
struct StackOverflowTests: View {
@State private var numOfPeople = "0"
var body: some View {
TextField("Total number of people", text: $numOfPeople)
.keyboardType(.numberPad)
.onReceive(Just(numOfPeople)) { newValue in
let filtered = newValue.filter { "0123456789".contains($0) }
if filtered != newValue {
self.numOfPeople = filtered
}
}
}
}
每当numOfPeople
变化时,过滤掉非数字值,然后比较过滤后的值,看看是否numOfPeople
应该第二次更新,用过滤后的输入覆盖错误的输入。
请注意,Just
出版商要求您import Combine
.
EDIT:
为了解释Just
发布者,请考虑以下概念性概述,了解当您更改中的值时会发生什么TextField
:
- Because
TextField
需要一个Binding
to a String
当字段的内容更改时,它也会将更改写回@State
多变的。
- 当一个变量被标记
@State
更改,SwiftUI 重新计算body
视图的属性。
- 在此期间
body
计算,一个Just
发布者已创建。联合起来有很多不同的发布者随着时间的推移发出值,但是Just
发布者“只”接受一个值(新值numberOfPeople
)并在被询问时发出它。
- The
onReceive
方法使得View
发布者的订阅者,在这种情况下,Just
我们刚刚创建的发布者。一旦订阅,它会立即向发布者请求任何可用的值,其中只有一个,即新值numberOfPeople
.
- 当。。。的时候
onReceive
订阅者收到一个值,它执行指定的闭包。我们的关闭可以通过以下两种方式之一结束。如果文本已经只是数字,那么它什么也不做。如果过滤后的文本不同,则将其写入@State
变量,它再次开始循环,但这次闭包将在不修改任何属性的情况下执行。
查看使用组合了解更多信息。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)