【问题标题】:How do I debug SwiftUI AttributeGraph cycle warnings?如何调试 SwiftUI AttributeGraph 循环警告?
【发布时间】:2020-11-02 06:41:36
【问题描述】:

我在使用 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 ===

【问题讨论】:

  • 您使用的是什么版本的 Xcode?我在 Xcode 11.4 中遇到过这个问题,它在以后的版本中奇迹般地自行解决了。
  • 发生在 Xcode 11.4 和 12 beta 2 中。
  • 我刚刚在 Xcode 12 Beta 2 中尝试过我的代码,但我的代码没有得到它,在 11.4 中尝试过,问题仍然存在。我想知道这是否只是一个 Xcode 问题......您是否能够创建一个可重现的示例,您可以将其作为 feedback 与 Apple 分享?我的问题是由于将 UIViewRepresentable 中的视图设置为隐藏造成的。
  • 我可能可以创建一个可重现的示例,但我在这里问的原因是因为我正在寻找一种更好的方法,而不是“只删除东西直到它工作”有点调试。
  • 能不能加一些demo代码来解决这个问题,因为好久没遇到了?

标签: xcode macos debugging swiftui


【解决方案1】:

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

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

这样你就可以为print_cycle设置符号断点

而且,它有多大帮助取决于您的场景,但肯定会在 Xcode 中生成错误堆栈。

【讨论】:

  • 这很有用。谢谢!您是如何知道警告消息是从哪里生成的?
  • $ nm /System/Library/PrivateFrameworks/AttributeGraph.framework/AttributeGraph
【解决方案2】:

对我来说,这个问题是由于我在用户仍在编辑文本字段时禁用了它。

要解决此问题,您必须首先将文本字段作为第一响应者(从而停止编辑),然后然后禁用文本字段。 我在stackoverflow article 中对此进行了更多解释。

【讨论】:

  • 哇,感谢为我工作的人
【解决方案3】:

对我来说,问题是通过不使用 UIActivityIndi​​cator 来解决的……但不知道为什么。下面的组件导致了问题。

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>
   ) {}
}

【讨论】:

    【解决方案4】:

    @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
                }
            }
        }
    }
    

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

    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
            }
        }
    }
    

    【讨论】:

    • 你能解释一下这是如何回答这个问题的吗?这看起来不像是一个答案,而是一个产生 AttributedGraph 循环的示例。
    【解决方案5】:

    对我来说,这个问题是由于在更改到包含 TextField 的 TabView 的选项卡之前尝试聚焦 TextField 引起的。

    在更改TabView 标签之后,只需关注TextField 即可解决此问题。

    这似乎类似于@wristbands was experiencing

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-23
      • 1970-01-01
      • 2011-05-11
      • 1970-01-01
      • 2020-03-04
      相关资源
      最近更新 更多