Chunking a List by DateComponent in SwiftUI with swift-algorithm

Colin Wren
4 min readOct 20, 2024

--

I’m currently doing a technical exploration of an idea I have. This idea involves a list view of journal entries a user enters over a long period of time, with new entries being added every week or so.

When thinking about the UX of this list and I need to ensure that the list remains easy to scan after the number of items in it grows. I settled on using an approach similar to how the Apple Journal app works, with the list sectioned by the month of the entry’s date.

Design wise this worked quite well, allowing me to find my place in the list easily as I scrolled down the list of items in my prototypes but when it came to the technical investigation this required a little more effort but luckily there’s an awesome Swift package called swift-algorithms that makes this a little easier.

The package has a couple of methods for chunking an array; you can chunk it into fixed sized chunks with chunked(ofCount:) , or you can provide some chunking logic with chunked(by:) or chunked(on:) , It’s very flexible.

Chunking an Array of journal entries by month

Let’s start with an example data model and view for showing the list, so that we know what it will look like when we render the un-chunked list.

Our journal entry data model will have a Date associated with it to represent the date that the entry was posted for and it will have a String that represents the text added for the entry.

A very simple data model for a Journal Entry

We will then have a view that renders the entries, that view will query all the entries and iterate over them to in a single List.

A basic list view of the entries, showing the entry text and the date

This results in a view like this where the entries are laid out in descending order.

A list of entries

When there’s only nine entries this is pretty manageable but when it grows it will be hard to quickly scroll to a specific date when we have 5+ years of entries. Creating sections based on the month so will allow the user to use the sections as a quick indicator of where they are.

Let’s begin by adding the swift-algorithms package. We can do this by using the “Add Package Dependencies” menu item in Xcode. At the time of writing swift-algorithms latest version is 1.2.0 , it goes without saying that should you install a different version things may not work the same.

Once the package is installed we can then import Algorithms to use any of the algorithms that swift-algorithmsoffers. The chunked algorithm extends the Arrayclass so we can access that as a property of our entries Array.

As we want to chunk our list on month we’ll want to use chunked(on:) which allows us to define the value to group the Array on. In this case we’ll extract the year and month DateComponents from the Entry date and use this to group the items.

chunked(on:) returns a 2-dimensional array, with the first item being the value for the chunk and then second item being the items from the original array that fall under that chunk. This returned value however isn’t going to be usable within our List and ForEach in our view so we need to transform the values.

I’ve chosen to wrap this into it’s own function. This function performs the chunking and then map s through the 2-dimensional array to turn the year-month chunking value into a String to show as the Section header and to cast the chunked items to an Array so they can be iterated over.

This function will perform the chunking and return a Tuple of a String and Entry array ready to be passed into the List

This can then be used in the EntryListView by creating a variable to call chunkEntries and then amending the initial ForEach to iterate over the chunks and create the Section with the chunk title and an inner ForEach for the items.

Calling chunkEntries and iterating over the sections and items inside

This then gives us a sectioned list, chunked on month of the year, with the month used as a Section title and the Entry s that belong to that month being shown under that Section .

The list of entries, chunked into sections based on the month the Entry was created

Handling .onDelete()

One of the harder parts of working with the chunked list is how to handle deleting a list item. Normally when deleting an item in the list you’ll set .onDelete(functionToCall) on the ForEach and that would provide you with an offset for the element in the list.

This gets more complicated when the list is chunked because that offset will be based on the chunk’s list not the offset in all items.

To solve this I passed in the key used for the chunk in the chunked list (in my case the title ) to the function that would handle deleting the list item and then I found that chunk and got the item at the offset it in it.

Deleting the list item in a chunked list

Summary

I found the chunked(on:) extension of swift-algorithms to provide a really flexible and powerful tool for splitting an Array based on a property of the underlying data.

Being able to easily add a chunked list into my apps empowers me to explore new ideas to build an amazing UX for my users while abstracting away some of the gory details of how the algorithms are working and I really appreciate the productivity boost.

--

--

Colin Wren
Colin Wren

Written by Colin Wren

Currently building reciprocal.dev. Interested in building shared understanding, Automated Testing, Dev practises, Metal, Chiptune. All views my own.

No responses yet