[英]Use Binding<Int> with a TextField SwiftUI
我目前正在构建一个页面以将玩家信息添加到本地数据库。 我为每个链接到播放器结构中的元素的输入都有一个 TextField 集合。
var body: some View {
VStack {
TextField("First Name", text: $player.FirstName)
.textFieldStyle(RoundedBorderTextFieldStyle())
TextField("Last Name", text: $player.LastName)
.textFieldStyle(RoundedBorderTextFieldStyle())
TextField("Email", text: $player.eMail)
.textFieldStyle(RoundedBorderTextFieldStyle())
TextField("Shirt Number", text: $player.ShirtNumber)
.textFieldStyle(RoundedBorderTextFieldStyle())
TextField("NickName", text: $player.NickName)
.textFieldStyle(RoundedBorderTextFieldStyle())
TextField("Height", text: $player.Height)
.textFieldStyle(RoundedBorderTextFieldStyle())
TextField("Weight", text: $player.Weight)
.textFieldStyle(RoundedBorderTextFieldStyle())
Button(action: {
submitPlayer(player: self.player)T
}) {
Text("Submit")
}
Spacer()
}
}
我的播放器结构是
struct Player: Hashable, Codable, Identifiable {
var id: Int
var FirstName: String
var LastName: String
var NickName: String
var eMail: String
var ShirtNumber: Int
var Height: Int
var Weight: Int
}
问题是 ShirtNumber、Height 和 Weight 都是 Int 值。 当我将它们绑定到 TextField 时,我收到一条错误消息,提示Cannot convert value of type 'Binding<Int>' to expected argument type 'Binding<String>'
。 我所研究的关于 SwiftUI 的所有内容都表明,不可能有一个绑定了 Int 值的 TextField。
我的问题是,是否可以创建一个新类来扩展 TextField 但只允许 Int 输入并绑定一个 Int 变量,像这样?
struct IntTextField: TextField {
init(_ text: String, binding: Binding<Int>) {
}
}
到目前为止,所有我已经能够找到的是从回答我的问题的一部分(只接受INT输入) 这个问题。 我正在寻找一种方法将它与Binding<Int>
结合起来。
谢谢您的帮助。
实际上,您可以使用TextField
绑定 manyTypes :
@State var weight: Int = 0
var body: some View {
Group{
Text("\(weight)")
TextField("Weight", value: $weight, formatter: NumberFormatter())
}}
当然也可以使用
TextField("", value: $value, formatter: NumberFormatter())
// .keyboardType(UIKeyboardType.decimalPad) // << uncomment for num pad
甚至使用数字键盘,但这并不能阻止将非数字字符输入到此类TextField
,直到未调用提交formatter
来验证输入。 也许 Apple 会给我们在未来即时验证输入的可能性,但不是现在,......所以我更喜欢不同的方式
这是我为数值(Int、Float、Double 等)设置文本字段的方法,它验证特定类型的输入和限制(比如不允许输入的值超过 Int 的最大允许值)。 希望它对某人也有帮助。 (当然可以根据使用需要进行字体、大小、颜色等配置)
struct NumberTextField<V>: UIViewRepresentable where V: Numeric & LosslessStringConvertible {
@Binding var value: V
typealias UIViewType = UITextField
func makeUIView(context: UIViewRepresentableContext<NumberTextField>) -> UITextField {
let editField = UITextField()
editField.delegate = context.coordinator
return editField
}
func updateUIView(_ editField: UITextField, context: UIViewRepresentableContext<NumberTextField>) {
editField.text = String(value)
}
func makeCoordinator() -> NumberTextField.Coordinator {
Coordinator(value: $value)
}
class Coordinator: NSObject, UITextFieldDelegate {
var value: Binding<V>
init(value: Binding<V>) {
self.value = value
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
let text = textField.text as NSString?
let newValue = text?.replacingCharacters(in: range, with: string)
if let number = V(newValue ?? "0") {
self.value.wrappedValue = number
return true
} else {
if nil == newValue || newValue!.isEmpty {
self.value.wrappedValue = 0
}
return false
}
}
func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) {
if reason == .committed {
textField.resignFirstResponder()
}
}
}
}
struct TestTextFieldWithNumbers: View {
@State private var value = 0
var body: some View {
VStack {
Text("Current value: \(value)")
Divider()
TextField("", value: $value, formatter: NumberFormatter())
// .keyboardType(UIKeyboardType.decimalPad)
Divider()
NumberTextField(value: $value)
.frame(height: 32)
}
}
}
struct TestTextFieldWithNumbers_Previews: PreviewProvider {
static var previews: some View {
TestTextFieldWithNumbers()
}
}
只是为了让它更容易观察。
改变这个:
TextField("", text: $intvalue)
到那个
TextField("Value", value: $amount, formatter: NumberFormatter())
试图让它在没有 UIKit 的情况下工作,因为我正在尝试构建一个小的 macOS 应用程序,所以 UIKit 不存在,所以找到了一个使用两个变量的解决方案(不是最干净但有效)
变量声明:
@State var minutes = 0
@State var minutesString = "0"
文本字段和步进器:
HStack {
TextField("minutes", text: self.$minutesString)
.onReceive(Just(self.minutesString)) { newValue in
let filtered = newValue.filter { $0.isNumber }
if filtered != newValue {
self.minutesString = filtered
self.minutes = Int(filtered) ?? -1
}
}
Stepper("minutes", value: $minutes).onChange(of: self.hours) { newValue in
self.minutesString = String(newValue)
}
.labelsHidden()
}
这将导致在写入 textField 或步进器时更改两个变量,并且不允许输入数字以外的任何内容。
我对整个快速的事情有点陌生,因此非常感谢任何反馈。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.