Query with Predicate

Dear all, I have the following two classes:

  1. Stagioni:
import SwiftData

@Model
class Stagione {
    @Attribute(.unique) var idStagione: String
    var categoriaStagione: String
    var miaSquadra: String
    @Relationship(deleteRule: .cascade) var rosa: [Rosa]?
    @Relationship(deleteRule: .cascade) var squadra: [Squadre]?
    @Relationship(deleteRule: .cascade) var partita: [CalendarioPartite]?
    
    init(idStagione: String, categoriaStagione: String, miaSquadra: String) {
        self.idStagione = idStagione
        self.categoriaStagione = categoriaStagione
        self.miaSquadra = miaSquadra
    }
}
  1. CalendarioPartite:
import SwiftData

@Model
class CalendarioPartite {
    var idGiornata: Int
    var dataPartita: Date
    var squadraCasa: String
    var squadraTrasferta: String
    var golCasa: Int
    var golTrasferta: Int
    
    var stagione: Stagione?
    
    init(idGiornata: Int, dataPartita: Date, squadraCasa: String, squadraTrasferta: String, golCasa: Int, golTrasferta: Int) {
        self.idGiornata = idGiornata
        self.dataPartita = dataPartita
        self.squadraCasa = squadraCasa
        self.squadraTrasferta = squadraTrasferta
        self.golCasa = golCasa
        self.golTrasferta = golTrasferta
    
    }
}

Now, I'd like to have a query which is showing in a view the list of partite depending on a selection of a specific Stagione. I've tried with the following query, but I'm getting the following error: "Instance member 'selectedStagione' cannot be used on type 'CalendarioCampionatoView'; did you mean to use a value of this type instead?"

@Query(filter: #Predicate<CalendarioPartite> { $0.stagione == selectedStagione}) private var partite: [CalendarioPartite] = []

What I'm doing wrong?

Thanks, A.

Replies

The variable is being used before any initialization has taken place. selectedStagione can be replaced with a constant or static value. Then within the body of the code, a refetch of the data, using the modelContext.fetch() can be done in response to some kind of change.

@Query(filter: #Predicate<CalendarioPartite> { $0.stagione == selectedStagione}) private var partite: [CalendarioPartite]

Thanks @MobileTen. So I am selecting the seasoned in the sidebar view as follows:

import SwiftData

struct SidebarView: View {
    
    @EnvironmentObject var navigationManager: NavigationStateManager
    @State private var isShowingSeasonSelection = false
    
    var body: some View {
        
        VStack {
            List(selection: $navigationManager.SelectionState) {
                
                Label("Home", systemImage: "house.fill")
                    .tag(SelectionState.home)
                
                Section("Squadra") {
                    
                    Label("Rosa", systemImage: "person.2.fill")
                        .tag(SelectionState.rosa)
                    
                    Label("Calendario", systemImage: "calendar")
                        .tag(SelectionState.calendarioSquadra)
                    
                }
                
                Section("Campionato") {
                    
                    Label("Calendario", systemImage: "calendar")
                        .tag(SelectionState.calendarioCampionato)
                    
                    Label("Classifica", systemImage: "list.bullet.rectangle.fill")
                        .tag(SelectionState.classifica)
                }
                
                Section("Allenatore") {
                    
                    Label("Esercizi", systemImage: "pencil.and.list.clipboard")
                        .tag(SelectionState.esercizi)
                }
                
                Section("Impostazioni") {
                    
                    Label("Impostazioni", systemImage: "gear")
                        .tag(SelectionState.settings)
                }
                
            }
            .listStyle(.sidebar)
            Spacer()
            Button(action: {
                            isShowingSeasonSelection.toggle()
                        }) {
                            Text("Seleziona Stagione")
                        }
                        .padding()
                        .buttonStyle(.borderedProminent)
                        .popover(isPresented: $isShowingSeasonSelection) {
                                        SeasonSelectionPopover(isShowingPopover: $isShowingSeasonSelection) // Passa la variabile di stato al popover
                                    }
            
            .navigationTitle("Stagione")
        }
        .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) // Imposta la larghezza per adattarsi al testo
                    
    }
}

struct SeasonSelectionPopover: View {
    
    @EnvironmentObject var navigationManager: NavigationStateManager
    @Binding var isShowingPopover: Bool // Binding per gestire la visualizzazione del popover
    @State private var selectedSeasonId: String = ""
    @Query(sort: \Stagione.idStagione, order: .reverse) private var seasons: [Stagione] // Assume che le stagioni siano disponibili
    
    var body: some View {
        VStack {
            Text("Seleziona la stagione:")
                .font(.headline)
                .padding()
            List(seasons, id: \.idStagione) { season in
                Button(action: {
                    // Imposta la stagione selezionata come quella corrente
                    navigationManager.selectedSeasonId = season.idStagione
                    // Chiudi il popover dopo la selezione
                    isShowingPopover = false
                }) {
                    Text(season.idStagione)
                }
            }
            .frame(width: 200, height: 200)
        }
        .onAppear {
            if let largestSeason = seasons.max(by: { $0.idStagione < $1.idStagione }) {
                selectedSeasonId = largestSeason.idStagione
            }
        }
    }
}

and I'd like to use it to filter data in the detail view "CalendarioCampionatoView":

import SwiftData

class CalendarioPartiteViewModel: ObservableObject {
    @Published var partite: [CalendarioPartite] = [] // Partite filtrate per stagione
    
    func fetchPartiteForStagione(stagioneId: String) {
        // Qui dovresti implementare la logica per recuperare le partite dal datastore filtrate per stagioneId
        @Query(filter: #Predicate<CalendarioPartite> {
            $0.stagione == selectedSeasonId}) private var partite: [CalendarioPartite]
        // Popola l'array partite con le partite corrispondenti
    }
}

struct CalendarioCampionatoView: View {
    @EnvironmentObject var navigationManager: NavigationStateManager
    @ObservedObject var calendarioPartiteViewModel = CalendarioPartiteViewModel()
    
    var body: some View {
        VStack {
            if calendarioPartiteViewModel.partite.isEmpty {
                Text("Non ci sono partite attualmente salvate per la stagione \(navigationManager.selectedSeasonId)")
            } else {
                List(calendarioPartiteViewModel.partite, id: \.idGiornata) { partita in
                    // Visualizza le informazioni della partita
                }
            }
        }
        .onAppear {
            // Recupera le partite filtrate per la stagione selezionata
            calendarioPartiteViewModel.fetchPartiteForStagione(stagioneId: navigationManager.selectedSeasonId)
            print("\(navigationManager.selectedSeasonId)")
        }
    }
}

I have here two errors and one warning:

  • Error: Attribute 'private' can only be used in a non-local scope
  • Error: Cannot find 'selectedSeasonId' in scope
  • Warning: Variable 'partite' was never used; consider replacing with '_' or removing it

As I quite new to SwiftUI, I'd really appreciate your experience to help me. I'm getting crazy since two days to solve this.

Thanks, A.