I want to have two unique alerts attached to the same Button
view. When I use the code below, only the alert on the bottom works.
I'm using the official release of Xcode 11 on macOS Catalina.
@State private var showFirstAlert = false
@State private var showSecondAlert = false
Button(action: {
if Bool.random() {
showFirstAlert = true
} else {
showSecondAlert = true
}
}) {
Text("Show random alert")
}
.alert(isPresented: $showFirstAlert) {
// This alert never shows
Alert(title: Text("First Alert"), message: Text("This is the first alert"))
}
.alert(isPresented: $showSecondAlert) {
// This alert does show
Alert(title: Text("Second Alert"), message: Text("This is the second alert"))
}
I expect first alert to show when I set showFirstAlert
to true and I expect the second alert to show when I set showSecondAlert
to true. Only the second alert shows when its state is true but the first one does nothing.
The second call to .alert(isPresented)
is overriding the first. What you really want is one Binding<Bool>
to denote whether the alert is presented, and some setting for which alert should be returned from the closure following .alert(isPresented)
. You could use a Bool for this, but I went ahead and did it with an enum, as that scales to more than two alerts.
enum ActiveAlert {
case first, second
}
struct ToggleView: View {
@State private var showAlert = false
@State private var activeAlert: ActiveAlert = .first
var body: some View {
Button(action: {
if Bool.random() {
self.activeAlert = .first
} else {
self.activeAlert = .second
}
self.showAlert = true
}) {
Text("Show random alert")
}
.alert(isPresented: $showAlert) {
switch activeAlert {
case .first:
return Alert(title: Text("First Alert"), message: Text("This is the first alert"))
case .second:
return Alert(title: Text("Second Alert"), message: Text("This is the second alert"))
}
}
}
}