How to manage Focus State using @FocusState in SwiftUI
Since iOS15, we can use @FocusState
property wrapper to manage the focus state of the fields, which will also trigger showing and dismissing the keyboard.
In iOS14 and before, we need some more work to do for the same result. You can find out the implementation details in the article: How to manage SwiftUI Focus State in iOS14 and before?
Using @FocusState in iOS15
For a more flexible solution, we can create an enum
for fields that we will use for focus state:
enum Field {
case title
case note
}
Next, we create a @FocusState
property that will hold the value of Field
enum
that should be in focus:
struct AddNewTaskView: View {
@FocusState private var focusedField: Field?
...
}
Then we should bind a view to a focus state using .focused(_:equals)
modifier:
TextField("Title", text: $viewModel.title)
.focused($focusedField, equals: .title)
Finally, in order to trigger the focused state, we should add a .task
modifier that will set the focused property when the view appears:
var body: some View {
VStack {
TextField(viewModel.taskType.placeholder, text: $viewModel.title)
.focused($focusedField, equals: .title)
}
.task {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
focusedField = .title
}
}
}
Here we're using a 0.15 seconds delay, but you should always test multiple times if the value works for you. A more complicated screen and slower device may need a 0.5 seconds delay. For instance, a popup view on iPad required at least 0.65 seconds delay in my case.
Conclusion
Managing focus state is a pretty common task in app development and luckily, we have a flexible built-in solution in iOS15.
I hope you enjoyed this article. If you have any questions, suggestions, or feedback, please let me know on Twitter.
Thanks for reading!