Using a custom image for a UITableViewCell's accessoryView and having it respond to UITableViewDelegate
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
A UITableViewCell can show a custom accessory view instead of the built-in disclosure indicator or detail button. The important detail is that a custom accessoryView is just a normal UIView; it does not automatically route taps through the same delegate callback used by the built-in accessory button types.
Why accessoryView Does Not Trigger the Usual Delegate Method
Many developers expect tableView(_:accessoryButtonTappedForRowWith:) to fire whenever the accessory area is tapped. That is only true for the standard accessory button types, such as .detailDisclosureButton. If you assign your own view to cell.accessoryView, UIKit does not treat it as that built-in control.
So there are really two different behaviors:
- built-in accessory button types participate in the dedicated delegate callback
- custom accessory views must handle interaction themselves
That is why setting a plain UIImageView as the accessory view usually does nothing when tapped. UIImageView is not a control, and even if you enable user interaction, UIKit still will not magically map the tap into the table view delegate method.
Use a UIButton as the Custom Accessory View
The practical fix is to use a UIButton with a custom image rather than a raw image view. A button gives you a normal target-action pathway while still letting you control the appearance.
This is the simplest robust pattern. The button owns the tap, and you resolve the tapped row by converting the button's position into the table view's coordinate space.
If You Want Delegate-Style Separation
Sometimes you want the cell to stay dumb and route the accessory action back to the controller in a cleaner way. A custom cell with a closure or protocol callback works well for that.
Then configure it in the table view controller:
This is easier to test and keeps the row-action logic readable.
Distinguish Row Selection from Accessory Taps
It is often useful to let a row tap do one thing and the accessory tap do something else. For example, tapping the row might open the item, while tapping the accessory could show details or a context menu.
You still use the normal delegate for row selection:
The accessory tap remains a separate control action. That separation is one of the main benefits of a custom accessory view.
Make the Control Feel Native
Custom accessory views are easy to implement badly. Keep a few details in mind:
- use a
UIButtonor anotherUIControl, not a passive image view - give the control a tap target large enough for comfortable use
- set an accessibility label so VoiceOver users know what the button does
- avoid doing heavy work directly inside the tap handler
For example:
That small addition matters if the icon alone does not explain the action.
Common Pitfalls
The most common mistake is expecting tableView(_:accessoryButtonTappedForRowWith:) to fire for a custom accessoryView. Another is using a UIImageView instead of a control, which leaves the icon visible but not properly interactive. Developers also sometimes rely on tag values for row lookup and forget that cell reuse can make that brittle if the tags are not updated carefully. A final issue is attaching the accessory action correctly but forgetting to preserve separate behavior between row selection and accessory taps, which makes the UI feel inconsistent.
Summary
- A custom
accessoryViewdoes not automatically participate in the built-in accessory delegate callback. - Use a
UIButtonor anotherUIControlfor a tappable custom image. - Resolve the row from the sender's position or route the event through a custom cell callback.
- Keep row selection and accessory actions separate when they represent different intents.
- Add accessibility metadata and a sensible touch target so the custom accessory behaves like a real iOS control.

