NSIndexPath
TableView
iOS Development
Swift
Objective-C

How to create NSIndexPath for TableView

Master System Design with Codemia

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

Introduction

NSIndexPath is one of the most commonly used classes in iOS development when working with UITableView and UICollectionView. It represents a path to a specific item within a nested collection, and in the context of table views, it identifies a cell by its section and row. Understanding how to create and use NSIndexPath correctly is essential for tasks like programmatic scrolling, cell selection, inserting or deleting rows, and responding to user interactions.

What is NSIndexPath?

Think of a table view as a two-level structure. The first level is the section (a group of related rows), and the second level is the row within that section. NSIndexPath encodes both of these values into a single object. For example, an index path with section 0 and row 2 points to the third row (zero-indexed) in the first section.

UIKit extends NSIndexPath with two convenience properties -- section and row -- that you will use constantly when working with table views.

Creating NSIndexPath in Swift

The most common way to create an NSIndexPath for a table view is through the IndexPath(row:section:) initializer. In Swift, you typically work with the IndexPath struct (which is bridged to NSIndexPath):

swift
1// Create an index path pointing to row 3 in section 1
2let indexPath = IndexPath(row: 3, section: 1)
3
4// Access the components
5print(indexPath.section) // 1
6print(indexPath.row)     // 3

You can use this index path to perform operations on the table view, such as scrolling to a specific cell:

swift
tableView.scrollToRow(at: indexPath, at: .middle, animated: true)

Or selecting a row programmatically:

swift
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)

Creating NSIndexPath in Objective-C

In Objective-C, you use the NSIndexPath class method indexPathForRow:inSection::

objc
1// Create an index path pointing to row 3 in section 1
2NSIndexPath *indexPath = [NSIndexPath indexPathForRow:3 inSection:1];
3
4// Access the components
5NSLog(@"Section: %ld", (long)indexPath.section);
6NSLog(@"Row: %ld", (long)indexPath.row);
7
8// Scroll to the cell
9[self.tableView scrollToRowAtIndexPath:indexPath
10                      atScrollPosition:UITableViewScrollPositionMiddle
11                              animated:YES];

Using NSIndexPath in UITableViewDataSource and Delegate

Index paths appear throughout the table view data source and delegate methods. Here is a typical implementation that demonstrates how you receive and use index paths:

swift
1func tableView(_ tableView: UITableView,
2               cellForRowAt indexPath: IndexPath) -> UITableViewCell {
3    let cell = tableView.dequeueReusableCell(
4        withIdentifier: "Cell", for: indexPath
5    )
6
7    // Use section and row to determine what data to display
8    let item = data[indexPath.section][indexPath.row]
9    cell.textLabel?.text = item.title
10
11    return cell
12}
13
14func tableView(_ tableView: UITableView,
15               didSelectRowAt indexPath: IndexPath) {
16    let selectedItem = data[indexPath.section][indexPath.row]
17    print("Selected: \(selectedItem.title) at section \(indexPath.section), row \(indexPath.row)")
18}

Inserting and Deleting Rows with NSIndexPath

When you modify the data source and need the table view to reflect changes, you pass arrays of index paths to the insertion and deletion methods:

swift
1// Insert a new row at the beginning of section 0
2let insertPath = IndexPath(row: 0, section: 0)
3data[0].insert(newItem, at: 0)
4tableView.insertRows(at: [insertPath], with: .automatic)
5
6// Delete the last row in section 1
7let deleteRow = data[1].count - 1
8let deletePath = IndexPath(row: deleteRow, section: 1)
9data[1].removeLast()
10tableView.deleteRows(at: [deletePath], with: .fade)

Wrap multiple insertions and deletions inside tableView.performBatchUpdates (or beginUpdates/endUpdates on older iOS versions) to animate them together smoothly.

Common Pitfalls

  • Off-by-one errors with zero-based indexing: Both row and section are zero-indexed. If your table has 5 rows, valid row values are 0 through 4. Passing row 5 will cause an out-of-range crash at runtime.
  • Mismatched data source and index paths: When inserting or deleting rows, you must update your data source array before calling insertRows(at:) or deleteRows(at:). If the data source count does not match what the table view expects after the update, you will get an NSInternalInconsistencyException.
  • Confusing row and item for collection views: UICollectionView uses IndexPath(item:section:) with an item property instead of row. Using indexPath.row on a collection view works due to bridging but can cause confusion when reading code. Use item for collection views and row for table views.
  • Storing index paths across reloads: Index paths become invalid after calling reloadData() because rows may have shifted. Never cache an index path and reuse it after a data reload. Instead, store the underlying data identifier and look up the current index path when needed.
  • Forgetting to handle multiple sections: Many beginners hardcode section 0 everywhere. If your table later gains multiple sections, all those hardcoded values will point to the wrong data. Always use indexPath.section to look up the correct data array, even if you currently have only one section.

Summary

  • NSIndexPath (bridged as IndexPath in Swift) identifies a cell in a table view by its section and row, both zero-indexed.
  • In Swift, create index paths with IndexPath(row:section:). In Objective-C, use [NSIndexPath indexPathForRow:inSection:].
  • Index paths are used throughout UITableViewDataSource and UITableViewDelegate methods for cell configuration, selection, and modification.
  • Always keep your data source in sync with the table view when inserting or deleting rows using index paths.
  • Use indexPath.row for table views and indexPath.item for collection views to keep your code clear and intention-revealing.

Course illustration
Course illustration

All Rights Reserved.