Swift Table View with Calendar Section Headers

Mazen Kilani
If let swift = Programming!
3 min readApr 15, 2021

Scenario

Our app contains book records in a Core Data database. We defined one of the Book attributes as Published Date. We wish to present a table view, sectioned by Publication Year, where each section contains the books published in that specific year.

Technique

We need to use the Swift DateFormatter() and the Calendar function of the Publication Date attribute to extract the Year component. Then we need to exclude any nil Publication Date values and sort the valid records by Publication Date. When building the table view sections, we shall extract the Year component and use it as the section header for books of the same publication year.

App Model

We based the article on the AppsGym Books model app, which is published on Apple’s App Store (as 8Books). You can review the Query result of ‘Books by Publication Year’ in the app. You can also download the complete Xcode project on AppsGym.com for free.

User Interface

The model app Queries menu shows options to list of book by different user-selected criteria (author, genre, publication year, etc.). The query result table view utilises dynamic section headers (year component of Publication Date) to group related records in a mini section, by publication year, within the overall list of books.

The file BooksByPubYearTableViewController.swift controls the layout, order, and navigation of the UITableViewController to show books by publication year. The app model sample data has multiple book publication dates in different years; the user can add their own books after removing the sample data as needed. The logic adds the appropriate Publication Year section header dynamically, after sorting the books by the book Publication Date.

The Queries.storyboard contains the storyboard for the Pub Year query.

Logic

  1. Declare the variable arrays that will contain the valid Query Books to allow section headers:

queryBooks: [Book], contains all fetched Core Data records

sectionHeaderTitles: [String], contains texts of all Publication Years

sectionBooks: [Book], contains books by sections

sectionBooksArrays [[Book]], contains arrays where each array is one section books

2. Retieve all the books from Core Data and populate queryBooks[]

3. Filter and sort quearyBooks[] by Publication Date

4. Loop through the queryBooks[] array and compare each book publication year (a calendar.component of the Publication Date) with the prior book year of publication (include special logic to the 1st time through the loop, so assume the year to be 1900 or similar)

5. Add the book to the sectionBooks[] array, the publication year to the sectionHeaderTitles[] and the similar publication year books to the sectionBooksArrays.

6. Show the table view, using the special section header functions:

heightForHeaderInSection(..) and viewForHeaderInSection(..)

Code

The Swift code snippets below are extracts from BooksByPublicationYearTableViewController.swift

viewDidLoad()

viewWillAppear()

SECTION HEADERS

cellForRowAt()

BooksByPublicatinYearTableViewController.swift didSelectRow() will navigate to the selected row Book Details view BookDetailsViewController.swift

We establish the connection between the ByPublicatinYear query and the Book Details by assigning a reference to the Book Details navigation controller, in Custom Class attribute Identity: Storyboard ID, and linking to the reference from the query Storyboard Reference ID.

didSelectRowAt() and prepare(for segue:)

UTILITIES

The article covered the complete logic and code to present a table view sectioned by a calendar function, in our example the Year of a Publication Date attribute on the Book record. Hope you find it useful. Thanks for reading!

--

--

Mazen Kilani
If let swift = Programming!

I published 47 Swift iOS apps/games and 2 Flutter Android apps. I share complete Xcode projects, free (no ads), at AppsGym.com.