How to use the @FocusState property wrapper in SwiftUI
Here’s how to make TextFields focused and not let a form close until the proper fields are filled out by the user.
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 TextField
s, 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 and while your down there hit the like and subscribe button for more SwiftUI and app development videos. I’ll see you in the next one!