UITableView
iOS Development
Swift
UITableViewCell
App Development

✔ Checkmark selected row in UITableViewCell

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Showing a checkmark on the selected UITableViewCell is a standard iOS pattern for single-choice settings screens. The implementation is simple, but common bugs appear when cells are reused, selection state is not stored in a data model, or UI updates happen without reloading visible rows. The correct design is to treat selection as app state first and cell accessory as a rendering detail. This keeps behavior correct across scrolling, reloads, and view re-entry.

Core Sections

Single selection with accessory checkmark

Store the selected index (or identifier) and configure cells based on it.

swift
1class OptionsVC: UITableViewController {
2    let items = ["Low", "Medium", "High"]
3    var selectedIndex: Int = 1
4
5    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
6        items.count
7    }
8
9    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
10        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
11        cell.textLabel?.text = items[indexPath.row]
12        cell.accessoryType = (indexPath.row == selectedIndex) ? .checkmark : .none
13        return cell
14    }
15}

Cell reuse is handled because accessoryType is set every time.

Update selection on tap

When user taps a row, update state and refresh affected rows.

swift
1override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
2    let previous = IndexPath(row: selectedIndex, section: 0)
3    selectedIndex = indexPath.row
4
5    tableView.reloadRows(at: [previous, indexPath], with: .automatic)
6    tableView.deselectRow(at: indexPath, animated: true)
7}

Reloading only two rows is efficient and keeps animations smooth.

Multi-select variant

For multiple choices, store a Set<Int> or IDs and apply .checkmark for membership.

swift
var selectedRows: Set<Int> = []

The same render-from-state pattern applies.

Persist selection

If setting must survive app relaunch, persist selected value and restore in viewDidLoad.

swift
UserDefaults.standard.set(selectedIndex, forKey: "quality_level")
selectedIndex = UserDefaults.standard.integer(forKey: "quality_level")

Persist identifiers instead of row numbers when list ordering can change.

Accessibility considerations

Checkmarked rows should still provide clear voice-over labels and selection hints.

Common Pitfalls

  • Setting checkmark only in didSelectRowAt without configuring it in cellForRowAt.
  • Forgetting cell reuse behavior and seeing stale checkmarks on scrolled rows.
  • Tracking selection by unstable row index when backing data can reorder.
  • Reloading entire table for single-selection changes and causing unnecessary flicker.
  • Not persisting settings selection when user expects state retention.

Verification Workflow

Test selection after scrolling, table reloads, and app relaunch. Verify that only one row is checkmarked in single-selection mode and that state matches persisted values. Add UI tests for tap-selection transitions and accessibility label announcements if the screen is user-critical.

text
11. Tap row and verify checkmark move
22. Scroll and verify reused cells
33. Reload table and verify state
44. Restart app and verify persistence
55. Validate VoiceOver selection cues

Production Readiness Checklist

Before considering the implementation complete, run a repeatable readiness pass that validates correctness, failure handling, and operational behavior in the same environment class where this solution will run. Start with a deterministic happy-path example and then exercise one malformed input and one resource-constrained scenario. Capture structured output such as status codes, key counters, and timing metrics so regressions are visible across revisions.

Document expected behavior boundaries in plain language so future maintainers can quickly understand what is guaranteed and what is best-effort. If configuration affects behavior, include the exact setting names and safe defaults in your runbook. For team workflows, add one lightweight automated check in CI to enforce these expectations on every change and keep debugging effort low when dependencies or runtime versions change.

text
11. Validate normal input path
22. Validate malformed or missing input path
33. Validate constrained-resource behavior
44. Record timing and error metrics
55. Confirm rollback or fallback behavior
66. Add CI smoke check for regression detection

Summary

Checkmark selection in UITableViewCell should be state-driven. Keep selected value in model state, render accessory in cellForRowAt, and update minimally on user tap. This approach is reliable, performant, and easy to maintain.


Course illustration
Course illustration

All Rights Reserved.