I'm trying to validate textFields to only allow numbers, a single period, or a single comma. In the code below I have two TextField
s, textFieldOne
and textFieldTwo
, in textFieldOne
I'm validating the field by calling the validateField()
method, everything works as expected for textFieldOne since I'm modifying its value inside the validateField()
method, but what I'm trying to do is make the validateField()
method more modular and be able to pass a State
variable to be able to use it with multiple fields to avoid code duplication but I haven't been able to figure out a way to pass the State
variable as a parameter in the validateField()
method. I tried passing it as validateField(textFieldName: Binding<String> ,newValue:String)
but I got errors saying that it couldn't convert type 'String' to expected type 'Binding<String>
.
How can I pass @State
textFieldOne and textFieldOne respectably as a parameter in the validateField()
method?
Again, what I'm trying to do is be able to call the validateField()
method inside the .onChange
modifier of each field, something like this... validateField(fieldName:textFieldOne, newValue: newValue)
. Basically, make the method reusable.
struct TextFieldNumbersOnly: View {
@State private var textFieldOne = ""
@State private var textFieldTwo = ""
var body: some View {
Form{
TextField("field one", text: $textFieldOne)
.keyboardType(.decimalPad)
.onChange(of: textFieldOne){newValue in
validateField(newValue: newValue)
}
TextField("field two", text: $textFieldTwo)
.keyboardType(.decimalPad)
.onChange(of: textFieldTwo){newValue in
//validateField(newValue: newValue)
}
}
}
func validateField(newValue:String){
let periodCount = newValue.components(separatedBy: ".").count - 1
let commaCount = newValue.components(separatedBy: ",").count - 1
if newValue.last == "." && periodCount > 1 || newValue.last == "," && commaCount > 1{
//it's a second period or comma, remove it
textFieldOne = String(newValue.dropLast())
}else{
let filtered = newValue.filter { "0123456789.,".contains($0) }
if filtered != newValue{
self.textFieldOne = filtered
}
}
}
}