Reputation: 6710
Working in HealthKit, I have an array of HealthKit Workouts that I need to organize into month and year (so that I can display workouts from Jan 2018, Feb 2018 etc.). What makes it difficult in my mind is I first need to check if there is a workout for a given month and year, if not I need to create the array for it, if there is I need to append to the existing array. I also am unsure of the best data model, I was thinking of using a [[Month:Year]]
but that doesn't seem very Swifty?
guard let workoutsUnwrapped = workouts else { return }
for workout in workoutsUnwrapped {
let calendar = Calendar.current
let year = calendar.component(.year, from: workout.startDate)
let month = calendar.component(.month, from: workout.startDate)
}
Upvotes: 2
Views: 978
Reputation: 318884
I'd start by creating a struct
to hold a year and month:
struct YearMonth: Comparable, Hashable {
let year: Int
let month: Int
init(year: Int, month: Int) {
self.year = year
self.month = month
}
init(date: Date) {
let comps = Calendar.current.dateComponents([.year, .month], from: date)
self.year = comps.year!
self.month = comps.month!
}
var hashValue: Int {
return year * 12 + month
}
static func == (lhs: YearMonth, rhs: YearMonth) -> Bool {
return lhs.year == rhs.year && lhs.month == rhs.month
}
static func < (lhs: YearMonth, rhs: YearMonth) -> Bool {
if lhs.year != rhs.year {
return lhs.year < rhs.year
} else {
return lhs.month < rhs.month
}
}
}
Now you can use this as a key in a dictionary where each value is an array of workouts.
var data = [YearMonth: [HKWorkout]]()
Now iterate your workouts:
guard let workouts = workouts else { return }
for workout in workouts {
let yearMonth = YearMonth(date: workout.startDate)
var yearMonthWorkouts = data[yearMonth, default: [HKWorkout]())
yearMonthWorkouts.append(workout)
data[yearMonth] = yearMonthWorkouts
}
Once this is done, all of your workouts are grouped by year/month.
You can build a sorted list of year/months for the keys in the dictionary.
let sorted = data.keys.sorted()
To apply this to a table view, use sorted
to define the number of sections. For each section, get the array of workouts from data
for the given YearMonth
of the corresponding section.
Upvotes: 7