SwiftUI 6 AttributeGraph warnings in console

On a MacBook Air M4 running macOS Sequoia 15.7.7, the following tiny code does warn inside the Xcode 26.3.

Here is the whole console output: === AttributeGraph: cycle detected through attribute 109592 === === AttributeGraph: cycle detected through attribute 109592 === === AttributeGraph: cycle detected through attribute 110216 === === AttributeGraph: cycle detected through attribute 110216 === === AttributeGraph: cycle detected through attribute 110284 === === AttributeGraph: cycle detected through attribute 110284 === === AttributeGraph: cycle detected through attribute 110216 === === AttributeGraph: cycle detected through attribute 109592 === === AttributeGraph: cycle detected through attribute 109592 === === AttributeGraph: cycle detected through attribute 110216 ===

Here is the full code: import SwiftUI

@main struct myApp: App { var body: some Scene { WindowGroup { BaseView() } } }

struct BaseView: View { @State private var isWorking: Bool = false

var body: some View {
    Button("Go") {
        Task {
            // AttributeGraph warnings
            await MainActor.run { isWorking = true }
            await MainActor.run { isWorking = false }

            // No warnings at all

// DispatchQueue.main.async { isWorking = true } // DispatchQueue.main.async { isWorking = false } } } .disabled(isWorking) .padding() } }

You can see with DispatchQueue.main.async {...}, warnings aren't there.

After a few days struggling with different AI support (Claude, ChatGPT, Perplexity), I didn't find any way to fix my own code. This tiny code is just there to show the issue.

I tested multiple workarounds without finding one that fits to my app context.

Thanks in advance for your support.

Thanks for the very interesting post.

I’m a little confused and I’m guessing too much for a Monday I think. The reason you are seeing this AttributeGraph: cycle detected warning comes down to how Swift Concurrency, I think.

However because your code is a minimal reproducible example, the correct fix depends on what you are actually doing between isWorking = true and isWorking = false in your real app. I don’t see how that code will produce anything.

In SwiftUI, Button actions are implicitly isolated to the @MainActor. When you create a Task { ... } inside a button action, that Task should inherits the MainActor. Because your Task is already on the MainActor, calling await MainActor.run { ... } does not actually suspend or switch threads. It should executes synchronously.

You are setting isWorking = true and then instantly setting isWorking = false in the exact same runloop without any code or anything to run between them?

If your real app does some heavy calculations or data parsing between the two state changes? You are accidentally blocking the MainActor? You need to move that work off the MainActor so the UI has time to update.

Looking forward to other engineers interpretation to make sure I didn’t missed the mark completely.

Albert  WWDR

Well, as you have properly guessed, this tiny code has only the benefit of showing the issue. In my app, I'm actually working with a function that can take up to 1-2 seconds max. The thing is that when I remove only the modifier .disabled(...), this issue vanishes.

Before posting this topic, I tried many things and when I finally got this tiny reproducible issue code, I then tried to work with DispatchQueue.main.async {...} to avoid the trap my code was driving me on.

My View is build like this:

private var isLoading: Bool {
    !isInitialized || isWorking
}

var body: some View {
    ZStack {
        VStack {
            Grid {
                GridRow {
                    ...
                    Button {
                        Task { await requestPermission() }
                   } label: { ... }
               }
                GridRow { ... }
            }
        }
        .disabled(isLoading)
        ....
        if isLoading {
            ProgressView()
        }
    }
}

where isInitialized is handled in the parent and isWorking is handled locally like this:

private func requestPermission() async {
    isWorking = true
    defer { isWorking = false }
    ...
}

But as far as the tiny code is able to reproduce the warnings, and most importantly as I'm still learning about Swift, I need support from stronger skills than mine.

SwiftUI 6 AttributeGraph warnings in console
 
 
Q