首页 > 解决方案 > 使用可观察对象帮助定义视图禁用标志时通过属性检测循环

问题描述

我有一个视图,我想在网络繁忙时禁用视图。我有以下可观察对象,其状态取决于网络的情况。这是在 SwiftUI 2.0 和 Mac BigSur 中。

class FeedModel: ObservableObject {
    enum CurrenState: Equatable {
        case none
        case loading
        case error
        case done
    }

   private (set) var feed: RssFeed?
   @Published private (set) var currentState: CurrenState = .none

   ... network code.
}

我的观点有以下代码:

struct FeedAddressSheet: View {
    @State var text: String = ""
    @Binding var isOpen: Bool
    @ObservedObject var model = FeedModel()

    public var body: some View {
        ZStack {
          VStack(alignment:.leading) {
              Text("Enter a feed address")
              TextField("", text: $text)
                .frame(idealWidth: 300)
              HStack {
                Spacer()
                Button("Cancel") {
                  isOpen = false
                }
                .keyboardShortcut(.cancelAction)
                Button("Add") {
                    model.load(address: text)
                }
                .keyboardShortcut(.defaultAction)
             }
           }
          .padding()
          .disabled(model.currentState == .loading)
          
          if model.currentState == .loading {
             ProgressView()
              .progressViewStyle(CircularProgressViewStyle())
          }
     }
     .alert(isPresented: Binding.constant(model.currentState == .error)) {
          Alert(title: Text("error"))
      }    
   }
}

我所在的行.disabled(model.currentState == .loading)导致以下错误。

=== AttributeGraph: cycle detected through attribute 247128 ===
=== AttributeGraph: cycle detected through attribute 242488 ===
=== AttributeGraph: cycle detected through attribute 249240 ===
=== AttributeGraph: cycle detected through attribute 249240 ===
=== AttributeGraph: cycle detected through attribute 250280 ===
=== AttributeGraph: cycle detected through attribute 250280 ===
=== AttributeGraph: cycle detected through attribute 242488 ===
=== AttributeGraph: cycle detected through attribute 252824 ===

我不知道为什么我要循环。

所以这似乎是文本字段的问题并且被绑定到状态变量。下面的代码显示了这个问题。

```struct ContentView: View {
@State var enabled = true
@State var text = ""

var body: some View {
    VStack {
        TextField("", text: $text)
        .padding()
        .disabled(!enabled)
        Button("Press me") {
            enabled.toggle()
        }
    }
}

}

标签: macosswiftui

解决方案


我相信你遇到了和我一样的问题。要修复它,您必须首先将文本字段作为第一响应者,然后禁用它:

struct ContentView: View {
@State var enabled = true
@State var text = ""

var body: some View {
    VStack {
        TextField("", text: $text)
        .padding()
        .disabled(!enabled)
        Button("Press me") {
            closeKeyboard()
            enabled.toggle()
        }
    }
}
func closeKeyboard() {
    UIApplication.shared.sendAction(
        #selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil
    )
}
}

这是我写的关于这个主题的stackoverflow 文章。


推荐阅读