Home > front end >  SwiftUI .confirmationDialog on List/ListRow is working on iOS 15, but is unreliable on iOS/iPadOS 16
SwiftUI .confirmationDialog on List/ListRow is working on iOS 15, but is unreliable on iOS/iPadOS 16

Time:11-11

SwiftUI .confirmationDialog on List/ListRow is working fine on iOS 15. I am using code like this example code:

struct ContentView: View {
    @StateObject var viewModel = ViewModel()

    var body: some View {
        
        NavigationView {
            List(viewModel.messages) { message in
                ListRow(message: message) { message in
                    withAnimation {
                        viewModel.delete(message)
                    }
                }
            }
            .navigationTitle("Messages")
            .onAppear { viewModel.fetch() }
        }
        .navigationViewStyle(StackNavigationViewStyle())
    }
}

struct ListRow: View {
    @State private var showConfirmation: Bool = false
    var message: Message
    var delete: (Message) -> Void
        
    var body: some View {
        
        Text(message.text)
        
            .swipeActions {
                Button( role: .destructive, action: { showConfirmation = true },
                        label: { Label("Delete", systemImage: "trash") })
            }
        
            .confirmationDialog(
                "Are you sure?",
                isPresented: $showConfirmation,
                titleVisibility: .visible,
                actions: { Button("Delete", role: .destructive) { withAnimation { delete(message) }}},
                message: { Text("You cannot undo deleting message \"\(message.text)\"") }
            )
    }
}

class ViewModel: ObservableObject {
    @Published var messages: [Message] = []
    
    func fetch() {
        messages = [Message(text: "Hello"),
                    Message(text: "How are you?"),
                    Message(text: "Do you have any plans?"),
                    Message(text: "Sailing?"),
                    Message(text: "Or Fishing?")]
    }
    
    func delete(_ message: Message?) {
        guard let message = message else { print("ERROR: no message to delete!"); return }
        messages.removeAll { $0.id == message.id }
    }
}

struct Message: Identifiable, Hashable {
    var text: String
    var id = UUID()
}

iOS 15 confDialog working as expected (animated gif):

iOS 15 confDialog OK

The same code on iOS 16 is delivering unexpected results, e.g. only triggering delete on the second try, etc. See below (animated gif):

iOS 16 confDialog issue

What should be done differently on iOS 16 to make the .configurationDialog modifier work as expected/as in iOS 15?

CodePudding user response:

.destructive automatically removes the row and that is probably clearing the showConfirmation state. You could prevent the row disappearing by changing the role to .none like this:

        .swipeActions {
            Button(role: .none, action: { showConfirmation = true },
                    label: { Label("Delete", systemImage: "trash") })
            .tint(Color.red)
        }
  • Related