BLACK FRIDAY: Save 50% on all my Swift books and bundles! >>

SOLVED: Section headers for a dynamic list

Forums > SwiftUI

Please, how can I create section headers for a dynamic list I'm fetching from Firestore. My model struct is:

struct MatchItem: Identifiable{
    var id: Int
    var localTeam: String
    var visitorTeam: String
    var minute: Int
    var status: String
    var timestamp: Date
    var league_id: Int
}

I have an array of MatchItem created thus:

var todaysLlist = [MatchItem]()

And my List is created like this:

List(todaysLlist){matchItem in
                    TodaysMatchItemCell(matchItem: matchItem)

                }
                .listStyle(PlainListStyle())

Please how can I group the array using the league_id property and create section headers in my list. Thank you very much.

1      

hi,

i would suggest first breaking out your todaysLlist into a dictionary, grouping by league_id:

let groups = Dictionary(grouping: todaysLlist, by: { $0.league_id })

the groups variable has the type [Int : [MatchItem]], where the keys of the dictionary are the values of league_id, and the values of the dictionary are arrays of MatchItems sharing the same league_id.

but you'll want to restructure this data into an array that can be used in a ForEach to produce sections. the simplest way to do this is to define a computed variable in your View with all of this together:

var groupData: [[MatchItem]] {
  let groups = Dictionary(grouping: todaysLlist, by: { $0.league_id })
  var returnData = [[MatchItem]]()
  for leagueID in groups.keys { // you may want to use groups.keys.sorted(), else the order is unpredictable
    returnData.append(groups[leagueID]!)
  }
  return returnData
}

now you can display the data in a View:

List {
  ForEach(groupData) { group in 
    Section(header: headerFor(group: group)) {
      ForEach(group) { matchItem in
        // display the view of matchItem
      }
    }
  }
}

the function to get the header for each group of MatchItems is simple: pick any on the MatchItems and read its league_id, because all of the MatchItems in the group have the same league_id. something like this:

func headerFor(group: [MatchItem]) -> some View {
  Text("league with id \(group[0].league_id)")
}

hope that gives you enough to work with,

DMG

  • (slight edits were made above about 15 minutes after the intial posting to correct some naming issues)

2      

Wow. This solves my problem. You are really appreciated. Thank you so much :D :)

1      

Save 50% in my WWDC sale.

SAVE 50% All our books and bundles are half price for Black Friday, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.