Here’s how to make TextFields focused and not let a form close until the proper fields are filled out by the user.
This article is also a video
WWDC 2021 introduced the property wrapper @FocusState. It can be used to set which textfields are in focus pretty easily. I’m going to open this form for adding a new bag of coffee an app I’m working on.
Notice how when I click on save it just closes the form and doesn’t dismiss the keyboard. The @FocusState can help fix that. First thing that needs to be added is an enum with the fields that we want to be required.
private enum Field { case name case style case roaster }
The enum needs to conform to the Hashable protocol so you can either force conformance by adding : Hashable or as long as the cases don’t have a value assigned you should be good since Swift will do that “automagically”.
Now, we need to add a variable with the property wrapper @FocusState private var focusField: Field
Then on the TextFields, add the focused modifier and what field it should be equal to
TextField("Name", text: $beans.name) .textFieldStyle(.roundedBorder) .focused($focusedField, equals: .name) TextField("Style", text: $beans.style) .textFieldStyle(.roundedBorder) .focused($focusedField, equals: .style) TextField("Roaster", text: $beans.roaster) .textFieldStyle(.roundedBorder) .focused($focusedField, equals: .roaster)
Next, let’s put some logic in to make sure these fields are filled and set the next focusedField
Button { if beans.name.isEmpty { focusedField = .name } else if beans.style.isEmpty { focusedField = .style } else if beans.roaster.isEmpty { focusedField = .roaster } else { if isEdit { beans.updateBean(context: viewContext) } else { beans.addBeansToData(context: viewContext) resetBeans() } showForm = false } }
Also, after a successful save, we should set the focusedfield to nil and dismiss the keyboard
Button { if beans.name.isEmpty { focusedField = .name } else if beans.style.isEmpty { focusedField = .style } else if beans.roaster.isEmpty { focusedField = .roaster } else { if isEdit { beans.updateBean(context: viewContext) } else { beans.addBeansToData(context: viewContext) resetBeans() } showForm = false focusedField = nil } }
Now, let’s run through the form one more time to just show it all together.
Hopefully that showed you how to use the @FocusState property wrapper. If you have any questions, then please drop a comment below.
Want my posts directly to your inbox?
Great! Sign up here!
Top comments (0)