I have a SwiftData model Player
and there should only ever be 0 or 1 in the database. When the user is on the Main Menu and taps to Start a New Game, I walk them through a couple of screens to pick the options for the game. Once all of the options are chosen, I delete all existing Player
objects and insert a new one. Then I dismiss all of those options picking screens.
Then what I want to happen is to automatically show the game view. But I'm not sure how to bind my .fullScreenCover()
to the Player.isShown
property on the first element in my SwiftData @Query
.
The code below doesn't work because: Cannot convert value of type 'Bool?' to expected argument type 'Binding<Bool>'
I'm still very new to Swift and SwiftUI, so my grasp on bindables and observables is still tenuous.
struct RootContentView: View {
@Query var activeplayers: [Player] // should only ever be 0 or 1
var body: some View {
ZStack {
// stuff
}
.fullScreenCover(isPresented: activeplayers.first?.isshown content: {
GameView()
})
}
}
How can I automatically show my GameView
screen based on the optional first element in my SwiftData @Query
?
I also tried just querying to see if any players exist with .isShown == true
and then binding to $activeplayers.isEmpty
(this is the reverse of the logic I actually want, but I was just trying to find SOME way to distill the data down to a single bool property and I figured I could work on reversing the logic later) but that didn't work either:
@Query (filter: #Predicate<Player> {
$0.isshown == true
}) var activeplayers: [Player]
// ...
// without the $, gives the error:
// Cannot convert value of type 'Bool' to expected argument type 'Binding<Bool>'
.fullScreenCover(isPresented: activeplayers.isEmpty content: {
GameView()
})
// with the $, gives the error:
// Cannot find '$activeplayers' in scope
.fullScreenCover(isPresented: $activeplayers.isEmpty content: {
GameView()
})
You could try this simple approach, using an extra @State var shouldShow
and setting it in .onAppear {...}
as shown in the example code
struct RootContentView: View {
@Environment(\.modelContext) private var modelContext
@Query var activeplayers: [Player]
@State var shouldShow = false // <-- here
var body: some View {
VStack {
Text("testing")
}
.fullScreenCover(isPresented: $shouldShow) { // <-- here
GameView()
}
// -- here
.onAppear {
if let player = activeplayers.first, let doShow = player.isshown {
shouldShow = doShow
}
}
}
}