It's a common scenario to make a text field first responder when it first appears. A typical example is the login screen. As soon as it appears, you want the account field to be in focus and the keyboard to appear. Then the user can start typing right way. But in SwiftUI, there is no native way to programmatically make any view first responder.
Luckily, it's very easy to wrap an UITextField
so you can call its becomeFirstResponder()
. Here is the wrapper view:
struct MyTextField: UIViewRepresentable {
typealias UIViewType = UITextField
@Binding var becomeFirstResponder: Bool
func makeUIView(context: Context) -> UITextField {
return UITextField()
}
func updateUIView(_ textField: UITextField, context: Context) {
if self.becomeFirstResponder {
DispatchQueue.main.async {
textField.becomeFirstResponder()
self.becomeFirstResponder = false
}
}
}
}
Notice the async
call. It is necessary because it's modifying the state and it isn't allowed in updateUIView
. If you forget, Xcode will warn you Modifying state during view update, this will cause undefined behavior.
To make it first responder when the view appears, just call it in .onAppear
:
struct ContentView: View {
@State private var becomeFirstResponder = false
var body: some View {
MyTextField(becomeFirstResponder: self.$becomeFirstResponder)
.onAppear {
self.becomeFirstResponder = true
}
}
}