0
0
iOS Swiftmobile~20 mins

Section headers and footers in iOS Swift - Mini App: Build & Ship

Choose your learning style9 modes available
Build: Contacts List
This screen shows a list of contacts grouped by the first letter of their names. Each group has a header showing the letter and a footer showing the number of contacts in that group.
Target UI
-------------------------
| Contacts List         |
-------------------------
| A                    |
| - Alice              |
| - Aaron              |
| 2 contacts           |
-------------------------
| B                    |
| - Bob                |
| - Bella              |
| - Bill               |
| 3 contacts           |
-------------------------
| C                    |
| - Carol              |
| 1 contact            |
-------------------------
Use UITableView to display contacts grouped by first letter
Show section headers with the letter
Show section footers with the count of contacts in that section
Use default UITableView styles
Support dynamic number of contacts and sections
Starter Code
iOS Swift
import UIKit

class ContactsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    let tableView = UITableView(frame: .zero, style: .grouped)
    let contacts = ["Alice", "Aaron", "Bob", "Bella", "Bill", "Carol"]
    var groupedContacts = [String: [String]]()
    var sectionTitles = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemBackground
        title = "Contacts List"

        // Group contacts by first letter
        // TODO: Implement grouping logic here

        // Setup table view
        tableView.dataSource = self
        tableView.delegate = self
        tableView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(tableView)

        NSLayoutConstraint.activate([
            tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
    }

    // TODO: Implement UITableViewDataSource methods

    // TODO: Implement UITableViewDelegate methods for headers and footers
}
Task 1
Task 2
Task 3
Task 4
Task 5
Solution
iOS Swift
import UIKit

class ContactsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    let tableView = UITableView(frame: .zero, style: .grouped)
    let contacts = ["Alice", "Aaron", "Bob", "Bella", "Bill", "Carol"]
    var groupedContacts = [String: [String]]()
    var sectionTitles = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemBackground
        title = "Contacts List"

        // Group contacts by first letter
        for contact in contacts {
            let firstLetter = String(contact.prefix(1))
            if groupedContacts[firstLetter] == nil {
                groupedContacts[firstLetter] = [contact]
            } else {
                groupedContacts[firstLetter]?.append(contact)
            }
        }

        // Sort section titles
        sectionTitles = groupedContacts.keys.sorted()

        // Setup table view
        tableView.dataSource = self
        tableView.delegate = self
        tableView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(tableView)

        NSLayoutConstraint.activate([
            tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return sectionTitles.count
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let key = sectionTitles[section]
        return groupedContacts[key]?.count ?? 0
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") ?? UITableViewCell(style: .default, reuseIdentifier: "cell")
        let key = sectionTitles[indexPath.section]
        if let contact = groupedContacts[key]?[indexPath.row] {
            cell.textLabel?.text = contact
        }
        return cell
    }

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sectionTitles[section]
    }

    func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
        let key = sectionTitles[section]
        let count = groupedContacts[key]?.count ?? 0
        return count == 1 ? "1 contact" : "\(count) contacts"
    }
}

We first group the contacts by their first letter using a dictionary. Then we sort the keys to get the section titles in order. The UITableViewDataSource methods use this data to show the correct number of sections and rows. The titleForHeaderInSection method returns the letter for each section header. The titleForFooterInSection method returns a string showing how many contacts are in that section, using singular or plural form correctly. This creates a clear grouped list with headers and footers.

Final Result
Completed Screen
-------------------------
| Contacts List         |
-------------------------
| A                    |
| - Alice              |
| - Aaron              |
| 2 contacts           |
-------------------------
| B                    |
| - Bob                |
| - Bella              |
| - Bill               |
| 3 contacts           |
-------------------------
| C                    |
| - Carol              |
| 1 contact            |
-------------------------
User can scroll through the list of contacts grouped by first letter
Section headers show the letter grouping
Section footers show the number of contacts in that group
Stretch Goal
Add the ability to tap a contact to show an alert with the contact's name
💡 Hint
Implement the UITableViewDelegate method didSelectRowAt and present a UIAlertController with the selected contact's name