SwiftUI sheet dismiss warning

I wanted to add a dismiss button to a sheet on SwiftUI. Since I also want to control the presentation from code, I put the presented state in a view model. Here is a simplified version of the code:

final class ViewController: ObservableObject {
    @Published var showSheet: Bool = false
}

struct ContentView: View {
    
    @StateObject private var viewController = ViewController()
    
    
    var body: some View {
        Button("Show sheet") {
            viewController.showSheet = true
        }
        .padding()
        
        .sheet(isPresented: $viewController.showSheet, content: {
            MySheetView()
        })
    }
}

struct MySheetView: View {
    
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        NavigationView {
            Text("Hello from the sheet")
            
                .toolbar {
                    ToolbarItem(placement: .navigationBarTrailing, content: {
                        Button("Dismiss") {
                            dismiss()
                        }
                    })
                }
        }
    }
}

If I use the dismiss button, I get the warning:

Publishing changes from within view updates is not allowed, this will cause undefined behavior.

just swiping down the sheet works fine.

Am I using something wrong here?

Xcode Version 14.0 (14A309)

Post not yet marked as solved Up vote post of andre07 Down vote post of andre07
2.2k views
  • Same. I encountered the same problem. Swiping down on sheets work fine, click on a button give purple warning.

  • Forgot to add this.... I ran the exact same code on macOS and no warning at all. On Mac there is no swipe down. So the only option is clicking dismiss button on a sheet. And after clicking the dismiss, no warning. Seems to be there is a bug in iOS.

Add a Comment

Replies

I just discovered that I have this same problem in a project I am working on. It has been driving me crazy trying to figure out where the warning was coming from and when I commented out the call to dismiss() it finally disappeared. Very annoying.

Put the Code back to the Main Queue 😎

You need to move the showSheet property out of the view controller class and keep it as part of MySheetView otherwise you'll keep getting complaints.. The view needs to be responsible for showing and dismissing sheets not an external view controller.

  • How can I present the sheet programatically then?

Add a Comment

ColGrenfell is correct. Had same problem. Moving property from a published property on the view model to a state variable on the view fixed the issue.

OK, moving the property from the ObservedObject to become a private view @State variable solves the issue. But, it was an @Publisehd inside an ObservedObject for a reason (being calculated from other conditions for example). So, no more @Published calculated properties?

  • Wondering the same thing. I have logic in my ViewModel that subscribes to the state of that @Published variable. If the view were to own it fully as a @State variable, it'd have to propagate that state back to the model on every change, which doesn't even seem possible to do when the sheet is dismissed with a swipe. Even if it was, it's highly undesirable to maintain duplicate state.

  • By the way another thing that seemed natural to try was to dismiss by changing the @Published property to false instead of calling dismiss(). This worked, but the warning was still there.

Add a Comment