1

I have a view that I want to disable a view wile the network is busy. I have the following observable object that has state depending on the what is going on with the network. This is in SwiftUI 2.0 and 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.
}

My view has the following 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"))
      }    
   }
}

The line where I have .disabled(model.currentState == .loading) is causing the following error.

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

I am not sure why I am getting a cycle.

So this appears to be an issue with the text field and being bound to a state var.. The following code is shows the issue.

```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()
        }
    }
}

}

4
  • 1
    Read this Apple Developer Forum post titled AttributeGraph: cycle detected in particular the two responses by Jim Dovey. That may help your understanding of what is occurring. Commented Sep 8, 2020 at 0:31
  • This might be helpful stackoverflow.com/a/63018486/12299030. Commented Sep 8, 2020 at 4:25
  • There is no way to see this that I can see in instruments or in the call stack. The call stack has none of my code. It has to do with changing the disabled flag on the view. Not matter what view. Commented Sep 8, 2020 at 21:40
  • @ScottAndrew I ran into the same issue and traced it down to conditionally showing the ProgressView, just like you did in your code snippet, like so: ` if model.currentState == .loading { ProgressView() .progressViewStyle(CircularProgressViewStyle()) } ` Commented Apr 28, 2021 at 19:10

1 Answer 1

0

I believe you're having the same problem I had. To fix it, you must first resign the text field as the first responder, and then disable it:

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

Here's the stackoverflow article I wrote on the subject.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.