Goal: I would like to limit SwiftUI TextField input by having 3 characters maximum.
Result: For some reason there is a way to input more than 3 characters into TextField
Steps:
Additional info
getter
and setter
doesn't print "1234" output which is really weirdQuestion: How to limit/validate SwiftUI TextField input for given example?
Playground code:
import SwiftUI
import PlaygroundSupport
import Combine
struct ContentView: View {
@State var inputValue: String = ""
@State var previousValue: String = ""
func getter() -> String {
print("getter called with ", inputValue)
return inputValue
}
func setter(_ newValue: String) {
print("setter called with ", inputValue)
if newValue.count > 3 {
inputValue = previousValue
} else {
inputValue = newValue
previousValue = inputValue
}
}
var body: some View {
TextField("", text: .init(get: getter, set: setter))
.frame(minWidth: 100)
}
}
PlaygroundPage.current.setLiveView(ContentView())
Also, even if you update the TextField definition like:
var body: some View {
TextField("", text: .init(get: { "test "}, set: { _ in }))
.frame(minWidth: 100)
}
to force "test" value always you still be able to input in every third attempt the additional character
This can be handled with .onChange
view modifier. Apologies if my syntax is a bit off, don't have my IDE immediately available.
In SwiftUI, you should never really use direct getters and setters.
@State var yourText = ""
var body: some View {
VStack {
// Your Text w/ @State Binding
}
.onChange(of: yourText) { newValue in
// Handle your constraints here.
// Check your value, if it exceeds your 3 char
// reset it back to the limit.
}
}
.onChange
has been changed to directly use the yourText
binding value inside of the closure, instead of the closure property.
.onChange(of: yourText) {
// Handle your constraints here.
// Use the `yourText` binding property instead of capturing `newValue`
}