繁体   English   中英

使用绑定<Int>使用 TextField SwiftUI

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM