SwiftUI validate input in textfields

Since SwiftUI 2 you can check the input using the onChange method and do any validations or changes there:

TextField("", value: $text)
    .onChange(of: text) { [text] newValue in
         // do any validation or alteration here.
         // 'text' is the old value, 'newValue' is the new one.
    }

Try to validate what you want in the TextField onRecive method like this:

class TextValidator: ObservableObject {

    @Published var text = ""

}

struct ContentView: View {

    @ObservedObject var textValidator = TextValidator()
    var body: some View {
        TextField("Type Here", text: $textValidator.text)
            .padding(.horizontal, 20.0)
            .textFieldStyle(RoundedBorderTextFieldStyle())
            .onReceive(Just(textValidator.text)) { newValue in
                let value = newValue.replacingOccurrences(
                    of: "\\W", with: "", options: .regularExpression)
                if value != newValue {
                    self.textValidator.text = value
                }
                print(newValue)
        }
    }
}

Here is possible approach using proxy binding, which still also allow separation of view & view model logic

class TextValidator: ObservableObject {

    @Published var text = ""

    func validate(_ value: String) -> String {
        value.replacingOccurrences(
                of: "\\W", with: "", options: .regularExpression
            )
    }
}


struct ContentView: View {

    @ObservedObject var textValidator = TextValidator()

    var body: some View {
        let validatingText = Binding<String>(
                get: { self.textValidator.text },
                set: { self.textValidator.text = self.textValidator.validate($0) }
                )
        return TextField("Type Here", text: validatingText)
            .padding(.horizontal, 20.0)
            .textFieldStyle(RoundedBorderTextFieldStyle())

    }
}

Tags:

Swift

Swiftui