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
            }
        }
    }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With