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):
The same code on iOS 16 is delivering unexpected results, e.g. only triggering delete on the second try, etc. See below (animated gif):
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)
}