You can check that the current value is valid via a computed Bool property. Then anywhere you want, you can place that check into your code.
SwiftUI recreates the ContentView body
every time your @State variable changes (which is best to be made private, FYI). It has some intelligence in re-rendering only what's needed, but essentially your entire View is reevaluated, and your calculated bool periodIsValid
retested with every keystroke.
Quite often the submit button is disabled while the form is invalid. Something like:
Button(...) {
...
}
.disabled(!periodIsValid)
To do it live, you can do a number of creative things with that live validation checking. Something really simple would be to make the text entered turn red if it is invalid:
struct ContentView: View {
@State private var validityPeriod = ""
var periodIsValid: Bool {
guard let days = Int(validityPeriod) else { return false}
guard days >= 1 && days <= 1000 else { return false }
return true
}
var body: some View {
NavigationView {
Form {
TextField("Validity Period (In Days)", text: $validityPeriod)
.foregroundColor(periodIsValid ? .primary : .red)
}
.navigationBarTitle("Validation")
}
}
}
Edit:
You can also limit the entry values...
Thinking more about this, you can actually perform instant-validation of the text field, which will prevent the entry of non-valid text.
To do this you use the didSet
property wrapper. Only hitch is that it doesn't work with @State
wrapper, so you'll have to use an @ObservedObject
instead. Pretty easy...
One note is that you may want to help people understand what's going on. If your interface doesn't already make it clear what values are okay, you may want to provide a hint when you squash an invalid entry.
class ValidityPeriod: ObservableObject {
@Published var validityPeriod = "" {
didSet {
// Allow blanks in the field, or they can't delete
if validityPeriod == "" { return }
// Check the entire value is good, otherwise ignore the change
let days = Int(validityPeriod) ?? 0
if days < 1 || days > 1000 { validityPeriod = oldValue }
// Pop alert or trigger any other UI instruction here
}
}
}
struct ContentView: View {
@ObservedObject var vp = ValidityPeriod()
var body: some View {
NavigationView {
Form {
TextField("Validity Period (In Days)", text: $vp.validityPeriod)
}
.navigationBarTitle("Validation")
}
}
}