Search code examples
xcodeswiftuixcode13

Is it possible to have a confirmationDialog on SwiftUI Menu?


I've seen an app that uses Menu where when you press the a button, I'm asked to "confirm". This brought me to refactor my app:


@State var confirmDeletion: Bool = false

VStack {

    Button(role: .destructive) {
        self.confirmDeletion = true
    } label: {
        Spacer()
        
        Text("Delete")
        
        Spacer()
    }.confirmationDialog(
        "Are you sure?",
        isPresented: $confirmDeletion,
        titleVisibility: .visible
    ) {
        Button("Yes", role: .destructive) {
    
            DispatchQueue.main.async {
                Task {
                    
                    await doSomeAsynWork()
                }
            }
        }
        
        Button("Cancel", role: .cancel) {}
    }
}

This works great. Now to refactor using Menu:


Menu {
    [..] // other buttons

    Button(role: .destructive) {
        print("I was called... and that's it")
        self.confirmDeletion = true
        
    } label: {
        Label("Delete", systemImage: "trash")
    }.confirmationDialog(
        "Are you sure?",
        isPresented: $confirmDeletion,
        titleVisibility: .visible
    ) {
        Button("Yes", role: .destructive) {
     
            DispatchQueue.main.async {
                Task {
                    
                    await doSomeAsynWork()
                }
            }
        }
        
        Button("Cancel", role: .cancel) {}
    }
   
} label: {
    Label("Menu", systemImage: "line.horizontal.3.decrease.circle")
}

I understand that when you press any menu button, it closes straight away so that's why the confirmationDialog does not work. Could I achieve a confirmationDialog with Menu?


Solution

  • Move it outside of Menu, like

    Menu {
        [..] // other buttons
    
        Button(role: .destructive) {
            print("I was called... and that's it")
            self.confirmDeletion = true
            
        } label: {
            Label("Delete", systemImage: "trash")
        }
       
    } label: {
        Label("Menu", systemImage: "line.horizontal.3.decrease.circle")
    }
    .confirmationDialog(                    // << here !!
            "Are you sure?",
            isPresented: $confirmDeletion,
            titleVisibility: .visible
        ) {
            Button("Yes", role: .destructive) {
         
                DispatchQueue.main.async {
                    Task {
                        
                        await doSomeAsynWork()
                    }
                }
            }
            
            Button("Cancel", role: .cancel) {}
        }