I would like to use a custom version of the standard disclosure accessory image in my UITableView. How can I do this? I'm hoping that sub-classing UITableViewCell is not necessary for something this basic.
9 Answers
You'll need to create a custom view and assign it to the accessoryView
property of the UITableViewCell
object. Something like:
myCell.accessoryView = [[ UIImageView alloc ]
initWithImage:[UIImage imageNamed:@"Something" ]];

- 71,764
- 9
- 59
- 54
-
8If I do this, I notice that the UITableViewDelegate method -[tableView:accessoryButtonTappedForRowWithIndexPath:] no longer gets called. Is that expected behavior? Is there a way to keep this method working? – Greg Maletic Jan 05 '10 at 01:54
-
There's some more explanation at http://stackoverflow.com/questions/869421/using-a-custom-image-for-a-uitableviewcells-accessoryview-and-having-it-respond – jarnoan Oct 06 '10 at 13:21
-
is it possible to do it using UIApperance proxy on UITableViewCell? – Claus Jul 03 '13 at 10:37
-
I used this approach to subclass UITableViewCell (DisclosureCell) and then all cells with the custom disclosure indicator inherit from DisclosureCell. – blwinters Jan 23 '16 at 22:03
- (UITableViewCell *)tableView:(UITableView *)tView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UIImage *indicatorImage = [UIImage imageNamed:@"Arrow.png"];
cell.accessoryView =[[[UIImageView alloc] initWithImage:indicatorImage] autorelease];
return cell;
}
well i do this with the help code given above

- 523
- 1
- 8
- 22
I ran into the same problem as Greg--the accessory view doesn't track (if you use an UIImageView)
I solved it like this:
UIImage * image = [ UIImage imageNamed:@"disclosure-button-grey.png" ] ;
UIControl * c = [ [ UIControl alloc ] initWithFrame:(CGRect){ CGPointZero, image.size } ] ;
c.layer.contents = (id)image.CGImage ;
[ c addTarget:self action:@selector( accessoryTapped: ) forControlEvents:UIControlEventTouchUpInside ] ;
cell.accessoryView = c ;
[ c release ] ;

- 15,922
- 4
- 48
- 73
-
1Why not just use a simple UIButton with an image, rather than fiddling with layer contents? – Daniel Rinser Aug 08 '12 at 13:40
-
I feel like I must have tried that and it didn't work for some reason? But sure, try with UIButton first... – nielsbot Aug 08 '12 at 19:52
-
When using a custom image, the location may change, and user may have problem clicking it since its frame may be small. best would be to add a subview button above the accessory view, this way you can handle size and location. – david72 Feb 19 '15 at 20:27
I'd do it as follows:
UIImageView *chevronImgVw = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"chevron_accessory_vw_img.png"]];
chevronImgVw.frame = CGRectMake(cell.accessoryView.frame.origin.x, cell.accessoryView.frame.origin.y, 10, 20);
cell.accessoryView = chevronImgVw;

- 42,008
- 16
- 111
- 154

- 7,983
- 3
- 57
- 80
There is a nice example from Apple showing how to use UIControl
to fulfill this kind of accessoryView customisation.
Overriding - (void)drawRect:(CGRect)rect
in UIControl is not the easiest way, but gives you lots of flexibility to style nice accessory views.

- 31,313
- 12
- 80
- 83
Swift 4 & 5:
This worked for me:
class MyCell: UITableViewCell {
// boilerplate...
fileprivate func commonInit() {
// This is the button we want, just need to change the image.
accessoryType = .detailButton
}
open override func layoutSubviews() {
super.layoutSubviews()
// Grab the "detail" button to change its icon. Functionality is set in the delegate.
if let submitButton = allSubviews.compactMap({ $0 as? UIButton }).first {
submitButton.setImage(#imageLiteral(resourceName: "icons8-enter-1"), for: .normal)
}
}
// everything else...
}
Best of all, this lets me use tableView(_:accessoryButtonTappedForRowWith:) to handle the button actions.
I used this for the button, but the same technique works for the disclosure image, [since/so long as] there is only one class in that branch of the hierarchy tree of the element you want to touch.
Oh, right, my code calls this:
extension UIView {
var allSubviews: [UIView] {
return subviews.flatMap { [$0] + $0.allSubviews }
}
}

- 1,656
- 1
- 19
- 19
In swift 4 & 5
myCell.accessoryView = UIImageView(image: UIImage(named: "Something"))

- 251
- 3
- 12
NOTE: Do NOT set a custom cell to tag:0. That tag is reserved for the textLabel view. If you set tags in Xcode Storyboard, you must set tags for custom views/labels to 1 or higher.
Note Apple's example:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath (NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];
UILabel *label;
label = (UILabel *)[cell viewWithTag:1];
label.text = [NSString stringWithFormat:@"%d", indexPath.row];
label = (UILabel *)[cell viewWithTag:2];
label.text = [NSString stringWithFormat:@"%d", NUMBER_OF_ROWS - indexPath.row];
return cell;
}

- 425
- 2
- 12
I tried the above code and it doesn't seem to work anymore, maybe due to the age of this post so I'll throw down my line that gave me the customized accessory view.
[cell setAccessoryView:[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"arrowBtn"]]];
Hope someone finds this useful.

- 311
- 2
- 26
-
2Tom, the accepted answer on this entry is exactly the same thing. What am I missing here? – jpm Jul 29 '14 at 00:01