SwiftUI: How To Programmatically Make a TextField First Responder

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
            }
    }
}