Football League calendar display view

Dear all, I'm quite new to SwiftUI and I'm trying to build my first app.

I have a data model file like the one below (I'm just posting a portion of it):

import Foundation

struct CalendarioPartite: Identifiable, Hashable, Equatable {
    let id = UUID()
    let stagione: String
    let giornata: Int
    let datapartita: String
    let squadracasa: String
    let golsquadracasa: Int
    let squadratrasferta: String
    let golsquadratrasferta: Int
    
    init(stagione: String, giornata: Int, datapartita: String, squadracasa: String, golsquadracasa: Int, squadratrasferta: String, golsquadratrasferta: Int) {
        self.stagione = stagione
        self.giornata = giornata
        self.datapartita = datapartita
        self.squadracasa = squadracasa
        self.golsquadracasa = golsquadracasa
        self.squadratrasferta = squadratrasferta
        self.golsquadratrasferta = golsquadratrasferta
    }
    
    static func testCalendario() -> [CalendarioPartite] {
        [CalendarioPartite(stagione: "2023/2024", giornata: 1, datapartita: "04/09/2023", squadracasa: "Castelnovese Castelnuovo", golsquadracasa: 1, squadratrasferta: "Junior Asca", golsquadratrasferta: 3),
..
    }
    
}

This is representing the data structure of 4 different days in a football league with teams and results. Now I'd like to build a view where the four different days are displayed according to a grid layout. Therefore I started to build the grid item for a single day. And this works as expected. The tricky part is then to use this as a function to be displayed into a LazyVGrid layout so that all the four days are displayed. I'm struggling with this in the view file:

import SwiftUI

struct CalendarioView: View {

    @State var Calendario: [CalendarioPartite] = CalendarioPartite.testCalendario()
    @State var stagione: String = "2023/2024"
    @State var totalePartite: Int = 4
    
    private var giornate = Array(1...4)
    private let adaptiveColumn = [GridItem(.adaptive(minimum: 150))]
    var partiteCampionato: [CalendarioPartite] {
        CalendarioPartite.testCalendario().filter{
            $0.stagione == stagione
        }
    }

    var body: some View {
        
        ScrollView {
            LazyVGrid(columns: adaptiveColumn, spacing: 20) {
                ForEach(giornate, id: \.self) {
                    giornata in
                    giornataDisplay()
                }
            }
            
        }.padding()
    }
    
    func giornataDisplay() {
        
       VStack {
            
            var partiteGiornata: [CalendarioPartite] {
                partiteCampionato.filter {
                    $0.giornata = giornate
                }
            }
            
            Text("Giornata \(giornate)")
                .fontWeight(/*@START_MENU_TOKEN@*/.bold/*@END_MENU_TOKEN@*/)
                .font(.headline)
                .foregroundColor(/*@START_MENU_TOKEN@*/.blue/*@END_MENU_TOKEN@*/)
                .padding()
            
            Grid {
                ForEach (partiteGiornata) { partita in
                    GridRow {
                        Text(partita.squadracasa)
                            .gridCellAnchor(UnitPoint(x: 0, y: 0.5))
                        Text("-")
                        Text(partita.squadratrasferta)
                            .gridCellAnchor(UnitPoint(x: 0, y: 0.5))
                        Text("=")
                        Text(partita.golsquadracasa, format: .number)
                        Text("-")
                        Text(partita.golsquadratrasferta, format: .number)
                    }
                    
                }

            }
            
        }
        .background(Color.gray.opacity(0.2))
        .clipShape(RoundedRectangle(cornerRadius: 15, style: .circular))
        
    }
    
}

In fact, I'm getting two different errors:

"No exact matches in reference to static method 'buildExpression'" in correspondence to the call of the function within the ForEach "Cannot assign to property: 'giornata' is a 'let' constant" within the function where I'm filtering the data to the "giornata" value. I guess this is depending by the fact that "giornate" var is an array. Am I right? Can you please assist me in achieving my desired result?

Thanks, A.

Answered by darkpaw in 784172022

I'm not near a Mac right now, but you're trying to iterate through the result that your giornataDisplay() function is returning, but it doesn't return anything. It looks like you're trying to create a View in that function without actually telling SwiftUI that this is a View. Move the stuff out of the function and into the ForEach loop, and see what happens.

You might, alternatively, want to change that func into a struct that returns a View for the data passed into it.

Accepted Answer

I'm not near a Mac right now, but you're trying to iterate through the result that your giornataDisplay() function is returning, but it doesn't return anything. It looks like you're trying to create a View in that function without actually telling SwiftUI that this is a View. Move the stuff out of the function and into the ForEach loop, and see what happens.

You might, alternatively, want to change that func into a struct that returns a View for the data passed into it.

Dear @darkpaw, I've done exactly what you suggested and got pretty good results from a data retrieval point of view (I'm displaying correctly the four football league days with the proper teams and results). Here below the code modification I've done:

import SwiftUI

struct CalendarioView: View {

    @State var Calendario: [CalendarioPartite] = CalendarioPartite.testCalendario()
    @State var stagione: String = "2023/2024"
    @State var totalePartite: Int = 4
    
    private var giornate = Array(1...4)
    private let adaptiveColumn = [GridItem(.adaptive(minimum: 1500))]
    var partiteCampionato: [CalendarioPartite] {
        CalendarioPartite.testCalendario().filter{
            $0.stagione == stagione
        }
    }

    var body: some View {
        
        ScrollView(.vertical) {
            
            LazyVGrid(columns: adaptiveColumn, spacing: 20) {
                
                ForEach(giornate, id:\.self) { giornata in
// Inizio schermata Giornata
                    VStack {
                         
                         var partiteGiornata: [CalendarioPartite] {
                             partiteCampionato.filter {
                                 $0.giornata == giornata
                             }
                         }
                         
                         Text("Giornata \(giornata)")
                             .fontWeight(/*@START_MENU_TOKEN@*/.bold/*@END_MENU_TOKEN@*/)
                             .font(.headline)
                             .foregroundColor(/*@START_MENU_TOKEN@*/.blue/*@END_MENU_TOKEN@*/)
                             .padding(.vertical)
                         
                         Grid {
                             ForEach (partiteGiornata) { partita in
                                 GridRow {
                                     Text(partita.squadracasa)
                                         .gridCellAnchor(UnitPoint(x: 0, y: 0.5))
                                     Text("-")
                                     Text(partita.squadratrasferta)
                                         .gridCellAnchor(UnitPoint(x: 0, y: 0.5))
                                     Text("=")
                                     Text(partita.golsquadracasa, format: .number)
                                     Text("-")
                                     Text(partita.golsquadratrasferta, format: .number)
                                 }
                                 
                             }

                         }
                         
                     }
                    .padding()
                    .background(Color.gray.opacity(0.2))
                    .clipShape(RoundedRectangle(cornerRadius: 15, style: .circular))
                    
// Fine schermata Giornata
                }
            }
            
        }
        
    }
}

Now, I have basically a problem: all the "giornata" are displayed vertically one-below-the other, while I would like to display them aligned on the left with a certain number on a row and then below (e.g. Day 1-2-3 on the same row and then the Day 4 below the Day 1) depending on the size of the screen. Is this possible? I think it depends on the size of the screen. Am I right?

Thanks in advance for your support, A.

Solved in the following way:

private let adaptiveColumn = [
        GridItem(.adaptive(minimum: 1000)),
        GridItem(.adaptive(minimum: 1000)),
        GridItem(.adaptive(minimum: 1000)),
    ]

Thanks @darkpaw for your support!

Football League calendar display view
 
 
Q