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.