Recommended Free Tools
iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Group SwiftUI records by a calendar-day key, sort the resulting groups, then display each group as a Section in a List. The key decision is what “same day” means for your app: the viewer’s local calendar, or a specific calendar and time zone.
Choose what counts as the same day
A Date represents a moment in time, not a calendar day. For personal activity lists, a common choice is to group each record by the start of its day in the current calendar:
calendar.startOfDay(for: entry.date)
Use the same calendar semantics when grouping and formatting the header. If records belong to a shared schedule or business process with a fixed time zone, configure a calendar for that time zone and use it consistently rather than relying on each viewer’s local settings. Calendar-aware keys avoid treating a localized display label as the underlying date logic.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Group and sort the records
Here is a reusable pattern for grouping entries, ordering the sections newest first, and sorting entries within each section newest first:
#1 Best Overall
struct Entry: Identifiable {
let id: UUID
let date: Date
let title: String
}
struct DayGroup: Identifiable {
let day: Date
let entries: [Entry]
var id: Date { day }
}
func groupedByDay(
_ entries: [Entry],
calendar: Calendar = .current
) -> [DayGroup] {
let groups = Dictionary(grouping: entries) { entry in
calendar.startOfDay(for: entry.date)
}
return groups.keys.sorted(by: >).map { day in
DayGroup(
day: day,
entries: groups[day, default: []].sorted { $0.date > $1.date }
)
}
}
For an agenda that moves forward through time, sort the day keys and entries oldest first instead. Do not rely on dictionary key iteration order for a timeline: explicitly sort keys to control the visible chronology.
Display each day as a List section
SwiftUI’s List provides a vertical collection, and a Section gives each date group a natural heading. Apple’s list guide also demonstrates iterating over groups with a ForEach and nesting another ForEach for the rows. Apple’s guide to displaying data in lists notes that each row inside a List must be a SwiftUI view.
Rank #2
struct EntryList: View {
let groups: [DayGroup]
var body: some View {
List {
ForEach(groups) { group in
Section {
ForEach(group.entries) { entry in
Text(entry.title)
}
} header: {
Text(group.day, format: .dateTime.month(.wide).day().year())
}
}
}
}
}
The example uses the day date as a group identifier, which works when each calendar day appears only once in the list. Keep each entry’s model ID stable and unique; SwiftUI uses identifiers to track changes as rows are inserted, removed, or reordered. Apple’s ForEach documentation explains identity-based data iteration.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Choose where to compute groups
| Approach | Useful when | Trade-off |
|---|---|---|
Precompute [DayGroup] in a model or view-model layer |
Groups are reused across screens, updated with incoming data, paginated, or tested separately. | Requires keeping the derived groups in sync with the source records. |
| Derive groups while composing the view | The collection is small and static, and a compact implementation is sufficient. | Grouping logic is less reusable and can be harder to isolate for testing. |
Apple documents the SwiftUI list and section structure, but does not require either data-shaping architecture. Choose based on reuse and update needs.
Rank #3
Format headers separately from grouping
Use the day key to decide which records belong together; format that date independently for the visible header. The sample uses Date.FormatStyle to produce a localized month, day, and year. Apple also documents DateFormatter for localized user-facing date strings. See Apple’s DateFormatter documentation.
Avoid grouping by formatted strings. Labels are for presentation and can vary by locale; using them as keys mixes display choices with calendar semantics.
Quick Recap
Best Value
Avoid common date-grouping errors
- Comparing full timestamps: Two records at different times on the same day are not equal as
Datevalues. Normalize them to a calendar day first. - Using UTC unintentionally: An item close to midnight can fall on a different calendar day in the user’s local time zone. Choose the app’s intended calendar and time zone explicitly.
- Using unstable row identity: Array indices can point to different records after insertions, deletions, or reordering. Use stable, unique model IDs instead.
- Assuming sections exist for empty days: Grouping records creates groups only for dates that have records. To show days with no entries, generate the desired date range separately and render those empty sections deliberately.
- Keeping stale day keys after settings change: If the app allows its calendar or time zone to change while the view remains active, recompute the groups using the new settings.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Free tools Windows power users keep installed
One-click scans. No signup required.

