NEW: Subscribe to Hacking with Swift+ and accelerate your learning! >>

SOLVED: grouped table by object's date property

Forums > SwiftUI

I have Person class,

class Person: Identifiable {
    var name: String
    var DOB: Date

    init(name: String, DOB: Date) {
        self.name = name
        self.DOB = DOB
    }
}

I have a PersonModelView which has an array of Persons.

var persons: [Person] = []

My SwiftUI View has a PersonModelView.

How would I go about displaying the persons in a List grouped by months based on each Person's upcoming birthdays?

The List would would looks this:

This month:
    Jane
    Paul
    Kevin
November, 2020:
    Sally
    Phoebe
    Cecil
December, 2020:
    Harold
    Ben
January, 2021:
    Cathy

Thanks, Gonzalo

   

hi,

if you just want the persons collected by month, from 1 through 12, use a dictionary and then rearrange its values (each value has type [Person]) by key into an array (which will have type [[Person]]. For example:

func personsByMonth() -> [[Person]] {
  guard !persons.isEmpty else { return [] }
  let dictionaryByMonth = Dictionary(grouping: persons, by: { $0.month })
  let months = Array(1...12) // rotate this array if you want to go from October to September
  return months.compactMap({ dictionaryByMonth[$0] })
}

the code above assumes that Person has a computed property month, an integer from 1 to 12, which you can compute from the DOB using its DateComponents. the compactMap operator is needed because some keys will not exist in the dictionary; only non-empty arrays of people by month will be returned as a result.

now you can display them in a grouped list:

List {
  ForEach(personsByMonth(), id: \.self) { personsInMonth in
    Section(header: Text(headerText(for: personsInMonth))) {
      ForEach(personsInMonth) { person in
        Text(person.name)
      } // end of ForEach
    } // end of Section
  } // end of ForEach
} // end of List

to figure out an appropriate headerText(for: personsInMonth) function, just recognize that all persons in personsInMonth share the same birthday month; so just read the month of any one of them, e.g., personsInMonth[0].month.

hope that helps,

DMG

   

Hacking with Swift is sponsored by Fernando Olivares

SPONSORED Ever ask for help and your reviewer immediately notices issues you missed? Fernando Olivares is a 10-year veteran from Big Nerd Ranch and Lambda School who can help hone your app building skills, and he's just launched a new book that does just that – use the code "hacking" to save $5!

Buy the book

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

Not logged in

Log in
 

Link copied to your pasteboard.