One of the issues encountered when creating a TextField (such as for a search box), is that the on-screen keyboard isn’t dismissed automatically when the user clicks outside the TextField
.
In the CWC+ iOS Databases course, Module 6, Lesson 5, Chris shows us how to dismiss the keyboard using pre-iOS 15 code, re:
...
VStack {
...
}
.onTapGesture {
// Resign first responder
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
Being on the primary VStack
means that the code is executed anywhere the user taps on the screen (because the VStack
fills the screen). However, I feel that this code is confusing and that there must be a better way of doing it today.
So I hunted around for a modern solution, and the key is using the new @FocusState
property wrapper, and then it’s as simple as adding
import SwiftUI
struct RecipeListView: View {
...
@FocusState private var inFocus: Bool
...
var body: some View {
NavigationView {
VStack (alignment: .leading) {
...
SearchBarView(
filterText: $filterBy
)
.padding([.bottom, .trailing])
.focused($inFocus)
...
}
...
.onTapGesture {
inFocus = false
}
}
}
}
When the user taps elsewhere on the screen (in the VStack
), the .onTapGesture
sets the inFocus
property to false which tells iOS that they’re outside the TextField
and so the keyboard is automatically dismissed.
And, when the user taps back inside the TextField
(which is within our SearchBarView
sub-view), the keyboard will pop up automatically as normal.