SwiftUI:如何在 UIViewRepresentable UITextField 上调用 becomeFirstResponder 时修复“通过属性检测到的 AttributeGraph 循环”

Ell*_*ott 2 uitextfield becomefirstresponder swift swiftui

我正在尝试使用其标记属性和 @Binding 将文本字段设置为第一响应者。由于我无法从 SwiftUI TextField 访问底层 UITextField 并.becomeFirstResponder()直接调用,我不得不使用UIViewRepresentable. 下面的代码有效,但会产生以下控制台消息=== AttributeGraph: cycle detected through attribute <#> ===

听起来我有内存泄漏和/或保留周期,我已将问题隔离到线路上,textField.becomeFirstResponder()但在检查了 Xcode 的内存图层次结构后,我看不出有什么问题?

非常感谢提供的任何帮助。

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()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Con*_*lon 10

凭直觉,我将 becomeFirstResponder() 放在异步调度中。这修复了警告。我猜在创建视图时会发生某种创建循环,然后您调用 becomeFirstResponder(),以便调用视图,从而触发 SwiftUI 查找尚未正确创建的视图(或其他像那样)

无论如何 - 这对我有用:

func updateUIView(_ uiView: UITextView, context: UIViewRepresentableContext<UITextViewWrapper>) {
    if uiView.text != self.text {
        uiView.text = self.text
    }
    if uiView.window != nil, !uiView.isFirstResponder {
        //This triggers attribute cycle if not dispatched
        DispatchQueue.main.async {
            uiView.becomeFirstResponder()
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 太感谢了。我的自定义 UIViewRepresentable 在 iOS 15 上崩溃了,但这修复了它! (2认同)