How to get UITableViewCell indexPath from the Cell?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
Getting the IndexPath of a UITableViewCell is a common requirement when handling button taps, gesture recognizers, or other interactions inside custom table view cells. The standard approach is tableView.indexPath(for: cell), which returns an optional IndexPath. The cell reference typically comes from the sender of an action (a button inside the cell) by walking up the view hierarchy or using a delegate/closure pattern. This article covers all major approaches.
Using indexPath(for:)
indexPath(for:) returns nil if the cell is not currently visible. This is the preferred API because it handles cell reuse correctly.
Button Inside a Cell (View Hierarchy)
convert(_:to:) translates the button's origin to table view coordinates. indexPathForRow(at:) returns the index path for the row at that point. This approach works regardless of how deeply nested the button is within the cell's view hierarchy.
Closure/Callback Pattern
The closure captures the indexPath from cellForRowAt. This is clean and avoids view hierarchy traversal. However, the captured indexPath can become stale if rows are inserted or deleted without reloading.
Delegate Pattern
The delegate pattern passes the cell itself back to the controller, where indexPath(for:) gets the current index path. This avoids stale index path issues.
Using Tag Property
Using tag is simple but fragile. Tags become incorrect after row insertions, deletions, or reordering unless the table is reloaded. Prefer indexPath(for:) or the closure pattern.
Common Pitfalls
- Cell not visible returns nil:
indexPath(for:)returnsnilfor cells that have scrolled off-screen and been recycled. Always handle the optional safely withguard letorif let. - Stale captured indexPath: Closures capturing
indexPathfromcellForRowAtbecome invalid after insertions or deletions. UseindexPath(for: cell)inside the closure for the current position. - Walking superview chain directly: Code like
cell.superview?.superview as? UITableViewbreaks across iOS versions because the view hierarchy changes. Useconvert(_:to:)withindexPathForRow(at:)instead. - Using tag for row identification:
cell.tag = indexPath.rowbreaks after row operations (insert, delete, move) unless you reload the entire table. It also conflicts with other uses of the tag property. - Adding targets multiple times:
addTargetincellForRowAtadds a new target each time the cell is reused. Either remove the previous target first or configure the target once in the cell'sawakeFromNib.
Summary
- Use
tableView.indexPath(for: cell)as the primary method — it returns the current index path - For buttons inside cells, use
convert(CGPoint.zero, to: tableView)+indexPathForRow(at:) - The closure pattern is concise but capture
[weak self]and re-fetch the index path if rows change - The delegate pattern is the most robust for complex cells with multiple interactive elements
- Avoid
tag-based approaches — they break silently when rows are inserted, deleted, or reordered
Related reading
- How to go back to previous page if back button is pressed in WebView?
- How to group by the elements of an array in Swift
- How to group by the elements of an array in Swift
- How to handle button clicks using the XML onClick within Fragments
- How to handle image scale on all the available iPhone resolutions?
- How to handle java.util.concurrent.TimeoutException android.os.BinderProxy.finalize timed out after 10 seconds errors?
- How to handle large Swift Project?
- How to handle notification when app in background in Firebase
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.