I'm attempting to set a textfield as first responder using its tag property and a @Binding. As I am unable to access the underlying UITextField from a SwiftUI TextField and call .becomeFirstResponder()
directly, I'm having to wrap a UITextField using UIViewRepresentable
. The code below works but results in the following console message === AttributeGraph: cycle detected through attribute <#> ===
.
It sounds like I have a memory leak and/or retain cycle, I've isolated the issue to the line textField.becomeFirstResponder()
but having inspected Xcode's Memory Graph Hierarchy I can not see what is wrong?
Any help provided is be much appreciated.
struct CustomTextField: UIViewRepresentable {
var tag: Int
@Binding var selectedTag: Int
@Binding var text: String
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UITextFieldDelegate {
var parent: ResponderTextField
init(_ textField: ResponderTextField) {
self.parent = textField
}
func textFieldDidChangeSelection(_ textField: UITextField) {
parent.text = textField.text ?? ""
}
}
func makeUIView(context: Context) -> UITextField {
let textField = UITextField(frame: .zero)
textField.tag = tag
textField.delegate = context.coordinator
return textField
}
func updateUIView(_ textField: UITextField, context: Context) {
if textField.tag == selectedTag, textField.window != nil, textField.isFirstResponder == false {
textField.becomeFirstResponder()
}
}
}