I'm trying to show an alert in Swift based on a computed property. Basically, whenever a user clicks on a button the value of "round" is updated. When more than 10 rounds have taken place, an alert shows.
To do this, I've created a boolean variable called "showingAlert". This has to be a @State var so that it gets set to false again when the user closes the alert.
However, the compiler tells me that a property wrapper like @State "cannot be applied to a computed property" :-(
This is the code that I've tried:
@State var round = 0
@State var showingAlert:Bool {round > 10 ? true : false}
func result(player: Int, app: Int) {
if player > app {
round += 1
}
else {
round += 1
}
}
var body: some View {
Button(action: {self.result(player: 1, app: 1)}) {
Text("Button")
}
.alert(isPresented: $showingAlert) {
Alert(title: Text("title"), message: Text("message"), dismissButton: .default(Text("Continue"))
)
}
Is there any way round this? I'd love to create an alert that shows without error messages.
I prefer putting logic in a model - separation of logic from the view - but here's something that works:
@State var round = 0
@State var showingAlert:Bool = false
func result(player: Int, app: Int) {
if player > app {
round += 1
} else {
round += 1
}
if round > 10 {
showingAlert.toggle()
}
}
Basically, move your check into your function. Notes:
if/else
because they both do the same thing.showingAlert
to true - let SwiftUI set it to false when the alert is dismissed.round
. Here's the code that does it:import SwiftUI
import Combine
class Model : ObservableObject {
var objectWillChange = PassthroughSubject<Void, Never>()
@Published var showingAlert = false {
willSet {
objectWillChange.send()
if newValue == false {
round = 0
}
}
}
var round = 0
func result(player: Int, app: Int) {
if player > app {
round += 1
} else {
round += 1
}
if round > 10 {
showingAlert.toggle()
}
}
}
struct ContentView: View {
@EnvironmentObject var model: Model
var body: some View {
Button(action: {self.model.result(player: 1, app: 1)}) {
Text("Button")
}
.alert(isPresented: self.$model.showingAlert) {
Alert(title: Text("title"), message: Text("message"), dismissButton: .default(Text("Continue")))
}
}
}
Note that there is only one variable (showingAlert
) marked as @Published
, that you can properly code against willSet
, and all you need to change in ContentView
is adding the EnvironmentObjectafter your add it to your
SceneDelegate` properly.
The first set of code will show the alert after the 11th tap, and then every tap after that. The second set of code will show the alert after the 11th tap, then every 11 taps after that.