9.5 C
New York
Tuesday, March 11, 2025

swift – Autofocus TextField programmatically in SwiftUI


Since Responder Chain isn’t introduced to be consumed by way of SwiftUI, so now we have to devour it utilizing UIViewRepresentable.
I’ve made a workaround that may work equally to the best way we use to do utilizing UIKit.

 struct CustomTextField: UIViewRepresentable {

   class Coordinator: NSObject, UITextFieldDelegate {

      @Binding var textual content: String
      @Binding var nextResponder : Bool?
      @Binding var isResponder : Bool?

      init(textual content: Binding,nextResponder : Binding , isResponder : Binding) {
        _text = textual content
        _isResponder = isResponder
        _nextResponder = nextResponder
      }

      func textFieldDidChangeSelection(_ textField: UITextField) {
        textual content = textField.textual content ?? ""
      }
    
      func textFieldDidBeginEditing(_ textField: UITextField) {
         DispatchQueue.primary.async {
             self.isResponder = true
         }
      }
    
      func textFieldDidEndEditing(_ textField: UITextField) {
         DispatchQueue.primary.async {
             self.isResponder = false
             if self.nextResponder != nil {
                 self.nextResponder = true
             }
         }
      }
  }

  @Binding var textual content: String
  @Binding var nextResponder : Bool?
  @Binding var isResponder : Bool?

  var isSecured : Bool = false
  var keyboard : UIKeyboardType

  func makeUIView(context: UIViewRepresentableContext) -> UITextField {
      let textField = UITextField(body: .zero)
      textField.isSecureTextEntry = isSecured
      textField.autocapitalizationType = .none
      textField.autocorrectionType = .no
      textField.keyboardType = keyboard
      textField.delegate = context.coordinator
      return textField
  }

  func makeCoordinator() -> CustomTextField.Coordinator {
      return Coordinator(textual content: $textual content, nextResponder: $nextResponder, isResponder: $isResponder)
  }

  func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext) {
       uiView.textual content = textual content
       if isResponder ?? false {
           uiView.becomeFirstResponder()
       }
  }

}

You should utilize this part like this…

struct ContentView : View {

@State non-public var username =  ""
@State non-public var password =  ""

// set true , if you wish to focus it initially, and set false if you wish to focus it by tapping on it.
@State non-public var isUsernameFirstResponder : Bool? = true
@State non-public var isPasswordFirstResponder : Bool? =  false


  var physique : some View {
    VStack(alignment: .heart) {
        
        CustomTextField(textual content: $username,
                        nextResponder: $isPasswordFirstResponder,
                        isResponder: $isUsernameFirstResponder,
                        isSecured: false,
                        keyboard: .default)
        
        // assigning the following responder to nil , as this shall be final textfield on the view.
        CustomTextField(textual content: $password,
                        nextResponder: .fixed(nil),
                        isResponder: $isPasswordFirstResponder,
                        isSecured: true,
                        keyboard: .default)
    }
    .padding(.horizontal, 50)
  }
}

Right here isResponder is to assigning responder to the present textfield, and nextResponder is to make the primary response , as the present textfield resigns it.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles