Bird
Raised Fist0
iOS Swiftmobile~20 mins

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

Choose your learning style10 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

Practice

(1/5)
1. What is the main purpose of section headers and footers in a UITableView?
easy
A. To change the background color of the table view
B. To add animations between table cells
C. To handle user input events
D. To organize and label groups of rows for better readability

Solution

  1. Step 1: Understand the role of section headers and footers

    Section headers and footers are used to separate and label groups of rows in a table view.
  2. Step 2: Identify their effect on user experience

    They improve readability by clearly marking different sections, making the list easier to navigate.
  3. Final Answer:

    To organize and label groups of rows for better readability -> Option D
  4. Quick Check:

    Section headers and footers = organize groups [OK]
Hint: Headers and footers label groups in lists [OK]
Common Mistakes:
  • Confusing headers with animations
  • Thinking headers change colors only
  • Assuming headers handle input
2. Which UITableViewDataSource method is used to provide a title for a section header?
easy
A. tableView(_:cellForRowAt:)
B. tableView(_:titleForHeaderInSection:)
C. tableView(_:heightForRowAt:)
D. tableView(_:didSelectRowAt:)

Solution

  1. Step 1: Recall UITableViewDataSource methods for headers

    The method tableView(_:titleForHeaderInSection:) returns the text for the header of a section.
  2. Step 2: Differentiate from other methods

    Other methods handle cells, row height, or selection, not headers.
  3. Final Answer:

    tableView(_:titleForHeaderInSection:) -> Option B
  4. Quick Check:

    Header title method = tableView(_:titleForHeaderInSection:) [OK]
Hint: Header titles use titleForHeaderInSection method [OK]
Common Mistakes:
  • Choosing cellForRowAt for headers
  • Confusing heightForRowAt with header titles
  • Selecting didSelectRowAt which is for taps
3. Given this code snippet, what will be displayed as the footer text for section 1?
func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
  if section == 0 {
    return "End of first section"
  } else if section == 1 {
    return "End of second section"
  }
  return nil
}
medium
A. "End of second section"
B. "End of first section"
C. nil (no footer text)
D. Runtime error

Solution

  1. Step 1: Analyze the method for section 1

    The method checks if section == 1 and returns "End of second section" for that case.
  2. Step 2: Confirm no errors or nil for section 1

    Since section 1 matches the else if condition, it returns the string, not nil or error.
  3. Final Answer:

    "End of second section" -> Option A
  4. Quick Check:

    Footer for section 1 = "End of second section" [OK]
Hint: Check section number in footer method [OK]
Common Mistakes:
  • Confusing section 0 and 1
  • Assuming nil means default text
  • Expecting runtime error from this code
4. Identify the error in this code for adding a section header title:
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
  if section == 0 {
    return "First Section"
  }
}
medium
A. Using String instead of String?
B. Wrong method name for header title
C. Missing return statement for all code paths
D. Incorrect parameter types

Solution

  1. Step 1: Check method return type and all paths

    The method returns String? but does not return anything if section != 0, causing a missing return error.
  2. Step 2: Confirm method signature correctness

    The method name and parameters are correct; the issue is missing return for other sections.
  3. Final Answer:

    Missing return statement for all code paths -> Option C
  4. Quick Check:

    All paths must return a value [OK]
Hint: All function paths must return a value [OK]
Common Mistakes:
  • Ignoring missing return for else cases
  • Thinking method name is wrong
  • Confusing return type with optional
5. You want to display a custom view as a section header instead of just text. Which UITableViewDelegate method should you implement?
hard
A. tableView(_:viewForHeaderInSection:)
B. tableView(_:titleForHeaderInSection:)
C. tableView(_:heightForRowAt:)
D. tableView(_:didSelectRowAt:)

Solution

  1. Step 1: Identify method for custom header views

    The method tableView(_:viewForHeaderInSection:) allows returning a UIView to use as a header.
  2. Step 2: Differentiate from text-only header method

    tableView(_:titleForHeaderInSection:) returns only a String, not a view.
  3. Final Answer:

    tableView(_:viewForHeaderInSection:) -> Option A
  4. Quick Check:

    Custom header view method = viewForHeaderInSection [OK]
Hint: Use viewForHeaderInSection for custom header views [OK]
Common Mistakes:
  • Using titleForHeaderInSection for views
  • Confusing row height with header view
  • Thinking didSelectRowAt affects headers
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard