I have a list of items. When I click an item Show Alert
I am showing an alert which displays two options: either Navigate
to dismiss the alert and navigate to the detail view or Cancel
which is supposed to just dismiss the alert.
The problem is that Cancel
still makes the NavigationLink
navigate.
What is a solution such that the second item navigates directly and the others show an alert that allows you to cancel.
This is a minimal reproducible example:
struct ContentView: View {
let items = ["1", "2", "3", "4"]
var body: some View {
NavigationView {
List {
ForEach(items, id: \.self) { item in
RowView(item: item)
}
}
}
}
}
struct RowView: View {
let item: String
@State private var isShowingNext = false
@State private var isShowingAlert = false
private var isShowingNextBinding: Binding<Bool> {
Binding(
get: {
!isShowingAlert && isShowingNext
}, set: {
isShowingNext = $0
}
)
}
var body: some View {
ZStack {
if item != "2" {
NavigationLink(
destination: Text("Hello"),
isActive: isShowingNextBinding,
label: {
Text(item)
}
).hidden()
Button(
action: {
isShowingAlert.toggle()
}, label: {
Text("\(item) Show Alert First")
}
)
.alert(isPresented: $isShowingAlert) {
Alert(
title: Text("Alert")
.foregroundColor(Color.red)
.font(.title),
message: Text("Hello"),
primaryButton: .destructive(
Text("Navigate"),
action: {
isShowingNext = true
}
),
secondaryButton: .cancel()
)
}
} else {
NavigationLink(
destination: Text("Hello"),
isActive: isShowingNextBinding,
label: {
Text("\(item) Show Directly")
}
)
}
}
}
}
Make sure to run it in iOS because on watchOS it works as expected.