debugging 如何调试SwiftUI AttributeGraph循环警告?

gcxthw6b  于 2022-11-24  发布在  Swift
关注(0)|答案(7)|浏览(142)

我在使用SwiftUI的应用程序中收到很多AttributeGraph循环警告。有什么方法可以调试导致它的原因吗?
控制台中显示的内容如下:

=== AttributeGraph: cycle detected through attribute 11640 ===
=== AttributeGraph: cycle detected through attribute 14168 ===
=== AttributeGraph: cycle detected through attribute 14168 ===
=== AttributeGraph: cycle detected through attribute 44568 ===
=== AttributeGraph: cycle detected through attribute 3608 ===
ep6jt1vc

ep6jt1vc1#

日志由(来自private AttributeGraph.framework)生成

AG::Graph::print_cycle(unsigned int) const ()

因此可以为print_cycle设置符号断点

它的帮助程度取决于您的场景,但在Xcode中肯定会出现错误生成的堆栈。

0h4hbjxa

0h4hbjxa2#

对我来说,这个问题是由于我禁用了一个文本字段,而用户仍然在编辑它。
要解决这个问题,你必须首先将文本字段作为第一响应者(从而停止编辑),然后禁用文本字段。

laik7k3q

laik7k3q3#

对我来说,这个问题是由于试图在更改到包含TextField的TabView的选项卡之前聚焦TextField而引起的。
在**更改TabView选项卡后,**只需聚焦TextField即可修复此问题。
这似乎与@wristbands的经历相似。

ycggw6v2

ycggw6v24#

对我来说,这个问题是通过不使用UIActivityIndicator解决的...虽然不知道为什么。下面的组件导致了问题。

public struct UIActivityIndicator: UIViewRepresentable {
   
   private let style: UIActivityIndicatorView.Style
   
   /// Default iOS 11 Activity Indicator.
   public init(
      style: UIActivityIndicatorView.Style = .large
   ) {
      self.style = style
   }
   
   public func makeUIView(
      context: UIViewRepresentableContext<UIActivityIndicator>
   ) -> UIActivityIndicatorView {
      return UIActivityIndicatorView(style: style)
   }
   
   public func updateUIView(
      _ uiView: UIActivityIndicatorView,
      context: UIViewRepresentableContext<UIActivityIndicator>
   ) {}
}
h9a6wy2h

h9a6wy2h5#

@Asperi这里是一个最小的例子来重现AttributeGraph cycle

import SwiftUI

struct BoomView: View {
    var body: some View {
        VStack {
            Text("Go back to see \"AttributeGraph: cycle detected through attribute\"")
                .font(.title)
            Spacer()
        }
    }
}

struct TestView: View {
    @State var text: String = ""
    @State private var isSearchFieldFocused: Bool = false
    
    var placeholderText = NSLocalizedString("Search", comment: "")
    
    var body: some View {
        NavigationView {
            VStack {
                FocusableTextField(text: $text, isFirstResponder: $isSearchFieldFocused, placeholder: placeholderText)
                    .foregroundColor(.primary)
                    .font(.body)
                    .fixedSize(horizontal: false, vertical: true)
                
                NavigationLink(destination: BoomView()) {
                    Text("Boom")
                }
                
                Spacer()
            }
            .onAppear {
                self.isSearchFieldFocused = true
            }
            .onDisappear {
                isSearchFieldFocused = false
            }
        }
    }
}

基于https://stackoverflow.com/a/59059359/659389FocusableTextField.swift

import SwiftUI

struct FocusableTextField: UIViewRepresentable {
    @Binding public var isFirstResponder: Bool
    @Binding public var text: String
    var placeholder: String = ""

    public var configuration = { (view: UITextField) in }

    public init(text: Binding<String>, isFirstResponder: Binding<Bool>, placeholder: String = "", configuration: @escaping (UITextField) -> () = { _ in }) {
        self.configuration = configuration
        self._text = text
        self._isFirstResponder = isFirstResponder
        self.placeholder = placeholder
    }

    public func makeUIView(context: Context) -> UITextField {
        let view = UITextField()
        view.placeholder = placeholder
        view.autocapitalizationType = .none
        view.autocorrectionType = .no
        view.addTarget(context.coordinator, action: #selector(Coordinator.textViewDidChange), for: .editingChanged)
        view.delegate = context.coordinator
        return view
    }

    public func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = text
        switch isFirstResponder {
        case true: uiView.becomeFirstResponder()
        case false: uiView.resignFirstResponder()
        }
    }

    public func makeCoordinator() -> Coordinator {
        Coordinator($text, isFirstResponder: $isFirstResponder)
    }

    public class Coordinator: NSObject, UITextFieldDelegate {
        var text: Binding<String>
        var isFirstResponder: Binding<Bool>

        init(_ text: Binding<String>, isFirstResponder: Binding<Bool>) {
            self.text = text
            self.isFirstResponder = isFirstResponder
        }

        @objc public func textViewDidChange(_ textField: UITextField) {
            self.text.wrappedValue = textField.text ?? ""
        }

        public func textFieldDidBeginEditing(_ textField: UITextField) {
            self.isFirstResponder.wrappedValue = true
        }

        public func textFieldDidEndEditing(_ textField: UITextField) {
            self.isFirstResponder.wrappedValue = false
        }
    }
}
u0sqgete

u0sqgete6#

对我来说,问题是我从主包动态加载AppIcon资产。

a1o7rhls

a1o7rhls7#

我在MacOS上的TabView中使用enum case作为标记值。最后一个case(共四个)触发了三个attributeGraph循环警告。(其他的都很好)。我现在使用Int变量(InspectorType.book.typeInt而不是InspectorType.book)作为我的选择变量,循环警告已经消失。
(我可以通过更改选择的类型注解掉有问题的行来演示这一点;我不能在另一个应用程序中重复它,所以显然还有其他的东西参与;我只是还没能确定另一个罪魁祸首。)

相关问题