SwiftUI: How to make TextField become first responder? SwiftUI: How to make TextField become first responder? swift swift

SwiftUI: How to make TextField become first responder?


Swift UI 3

As of Xcode 13, you can use the focused modifier to make a view become first responder.


Swift UI 1/2

It doesn't seem to be possible at the moment, but you can implement something similar yourself.

You can create a custom text field and add a value to make it become first responder.

struct CustomTextField: UIViewRepresentable {    class Coordinator: NSObject, UITextFieldDelegate {        @Binding var text: String        var didBecomeFirstResponder = false        init(text: Binding<String>) {            _text = text        }        func textFieldDidChangeSelection(_ textField: UITextField) {            text = textField.text ?? ""        }    }    @Binding var text: String    var isFirstResponder: Bool = false    func makeUIView(context: UIViewRepresentableContext<CustomTextField>) -> UITextField {        let textField = UITextField(frame: .zero)        textField.delegate = context.coordinator        return textField    }    func makeCoordinator() -> CustomTextField.Coordinator {        return Coordinator(text: $text)    }    func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<CustomTextField>) {        uiView.text = text        if isFirstResponder && !context.coordinator.didBecomeFirstResponder  {            uiView.becomeFirstResponder()            context.coordinator.didBecomeFirstResponder = true        }    }}

Note: didBecomeFirstResponder is needed to make sure the text field becomes first responder only once, not on every refresh by SwiftUI!

You would use it like this...

struct ContentView : View {    @State var text: String = ""    var body: some View {        CustomTextField(text: $text, isFirstResponder: true)            .frame(width: 300, height: 50)            .background(Color.red)    }}

P.S. I added a frame as it doesn't behave like the stock TextField, meaning there's more stuff going on behind the scenes.

More on Coordinators in this excellent WWDC 19 talk:Integrating SwiftUI

Tested on Xcode 11.4


Using SwiftUI-Introspect, you can do:

TextField("", text: $value).introspectTextField { textField in    textField.becomeFirstResponder()}


For anyone who ended up here but faced crashed using @Matteo Pacini's answer, please be aware of this change in beta 4: Cannot assign to property: '$text' is immutable about this block:

init(text: Binding<String>) {    $text = text}

should use:

init(text: Binding<String>) {    _text = text}

And if you want to make the textfield become first responder in a sheet, please be aware that you cannot call becomeFirstResponder until the textfield is shown. In other words, putting @Matteo Pacini's textfield directly in sheet content causes crash.

To solve the issue, add an additional check uiView.window != nil for textfield's visibility. Only focus after it is in the view hierarchy:

struct AutoFocusTextField: UIViewRepresentable {    @Binding var text: String    func makeCoordinator() -> Coordinator {        Coordinator(self)    }    func makeUIView(context: UIViewRepresentableContext<AutoFocusTextField>) -> UITextField {        let textField = UITextField()        textField.delegate = context.coordinator        return textField    }    func updateUIView(_ uiView: UITextField, context:        UIViewRepresentableContext<AutoFocusTextField>) {        uiView.text = text        if uiView.window != nil, !uiView.isFirstResponder {            uiView.becomeFirstResponder()        }    }    class Coordinator: NSObject, UITextFieldDelegate {        var parent: AutoFocusTextField        init(_ autoFocusTextField: AutoFocusTextField) {            self.parent = autoFocusTextField        }        func textFieldDidChangeSelection(_ textField: UITextField) {            parent.text = textField.text ?? ""        }    }}