Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI for macOS - trigger sheet .onDismiss problem

In a multiplatform app I'm showing a sheet to collect a small amount of user input. On iOS, when the sheet is dismissed, the relevant .onDismiss method is called but not on macOS.

I've read that having the .onDismiss in the List can cause problems so I've attached it to the button itself with no improvement. I've also tried passing the isPresented binding through and toggling that within the sheet itself to dismiss, but again with no success.

I am employing a NavigationView but removing that makes no difference. The following simplified example demonstrates my problem. Any ideas? Should I even be using a sheet for this purpose on macOS?

I just want to make clear that I have no problem closing the sheet. The other questions I found were regarding problems closing the sheet - I can do that fine.

import SwiftUI

@main
struct SheetTestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

struct ContentView: View {
    var body: some View {
        NavigationView {
            ListView()
        }
    }
}

The List view.

struct ListView: View {
    
    @State private var isPresented: Bool = false
    
    var body: some View {
        VStack {
            Text("Patterns").font(.title)
            
            Button(action: {
                isPresented = true
            }, label: {
                Text("Add")
            })
            .sheet(isPresented: $isPresented, onDismiss: {
                doSomethingAfter()
            }) {
                TestSheetView()
            }
            
            List {
                Text("Bingo")
                Text("Bongo")
                Text("Banjo")
            }
            .onAppear(perform: {
                doSomethingBefore()
            })
        }
    }
    
    func doSomethingBefore() {
        print("Johnny")
    }
    
    func doSomethingAfter() {
        print("Cash")
    }
}

This is the sheet view.

struct TestSheetView: View {
    
    @Environment(\.presentationMode) var presentationMode
    
    @State private var name = ""
    
    var body: some View {
        Form {
            TextField("Enter name", text: $name)
                .padding()
            
            HStack {
                Spacer()
                Button("Save") {
                    presentationMode.wrappedValue.dismiss()
                }
                Spacer()
            }
        }
        .frame(minWidth: 300, minHeight: 300)
        .navigationTitle("Jedward")
    }
}
like image 744
Magnas Avatar asked Nov 27 '25 07:11

Magnas


1 Answers

Bad issue.. you are right. OnDismiss is not called. Here is a workaround with Proxybinding

var body: some View {
    VStack {
        Text("Patterns").font(.title)
        
        Button(action: {
            isPresented = true
        }, label: {
            Text("Add")
        })
        
        List {
            Text("Bingo")
            Text("Bongo")
            Text("Banjo")
        }
        .onAppear(perform: {
            doSomethingBefore()
        })
    }
    .sheet(isPresented: Binding<Bool>(
            get: {
                isPresented
            }, set: {
                isPresented = $0
                if !$0 {
                    doSomethingAfter()
                }
            })) {
        TestSheetView()
    }
}
like image 82
davidev Avatar answered Nov 28 '25 20:11

davidev