SwiftUI:如何在UIViewRepresentable UITextField上调用be成为FirstResponder时修复'AttributeGraph cycle detected th



我正在尝试使用其标签属性和@Binding将文本字段设置为第一响应者。由于我无法从 SwiftUI TextField 访问底层 UITextField 并直接调用.becomeFirstResponder(),因此我必须使用UIViewRepresentable包装 UITextField。下面的代码有效,但会导致以下控制台消息=== 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()
}
}
}

凭直觉,我把be成为FirstResponder((放在一个异步调度中。这将修复警告。 我猜在创建视图时会发生某种创建循环,并且您调用 becomFirstResponder((,以便调用视图,这会触发 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()
}
}
}

困惑的Vorlon的回答对我有用,但它仍然有点不稳定,因为似乎uiView.isFirstResponder没有返回我在导航到另一个视图时所期望的内容。这导致uiView.becomeFirstResponder()被称为意想不到的时间。

解决此问题的另一种方法是在协调员中添加一个布尔值,以跟踪您是否已经将该字段设为第一响应者。

func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<FocusableTextField>) {
uiView.text = text
if isFirstResponder && !context.coordinator.didBecomeFirstResponder {
uiView.becomeFirstResponder()
context.coordinator.didBecomeFirstResponder = true
}
}
class Coordinator: NSObject {
@Binding var text: String
var didBecomeFirstResponder: Bool = false
init(text: Binding<String>) {
_text = text
}
@objc public func textViewDidChange(_ textField: UITextField) {
self.text = textField.text ?? ""
}
}

我也在崩溃时遇到=== AttributeGraph: cycle detected through attribute <#> ===,但事实证明崩溃是由其他原因引起的。

崩溃实际上是由未链接到应用程序本身的依赖项丢失引起的。

我还检查了仪器,也没有显示内存泄漏或保留周期。

缺少的依赖项是另一个框架,它提供了我们的 SwiftUI 代码中使用的一些 SwiftUI 视图修饰符。但是有人不小心从应用程序的"链接二进制文件与库"和"嵌入框架"构建阶段中删除了该框架。一旦我将依赖项添加到正确的构建阶段并添加到主应用程序方案中构建,那么有问题的日志消息就停止出现(并且崩溃也停止了(。

换句话说,=== AttributeGraph: cycle detected through attribute <#> ===似乎并不直接导致崩溃或内存泄漏,但可能与导致 SwiftUI 无法解析视图层次结构的其他问题(如缺少依赖项(有关。

扬子晚报.

我在父视图中删除了此代码,警告消失了,

.focusedValue(.path, $binding)

最新更新