Am using UITableViewRowAction in "editActionsForRowAtIndexPath" method. I can change the backgroundcolor of UITableViewRowAction, but am not able to change the title color. But I would like to change the color of the UITableViewRowAction. Any inputs on this regard will be appreciable.

- 5,522
- 35
- 29

- 723
- 2
- 7
- 19
-
RowAction means what? You can use cell.titlelabe.color for it. is it helpful for you? – Rajpal Thakur Nov 12 '14 at 13:02
-
From iOS 8, sdk allows us to use a new delegate method "editActionsForRowAtIndexPath". This method will be triggered once we swipe the tableviewcell. So using UITableViewAction we will access the "delete button" on swiping. – GJDK Nov 12 '14 at 13:17
-
ohk...are you not able to change tiltelable text color? – Rajpal Thakur Nov 12 '14 at 13:19
11 Answers
There is one way that can achieve what you are looking for. But it is little tricky though.
Example of result:
The idea of this trick is that you can actually modify background color. This means that you can set UIColor's +colorWithPatternImage: and set an bitmap image that match desired styling. This can be achieved either by creating image using graphic editor or by rendering it using for example Core Graphics. The only problem with this solution is, that you have to mimic original title length with you specific text attributes to make it work properly and also you must set title for table view row action as string of white spaces so that table view cell will prepare enough space for you "custom action button". Creating static png assets in photoshop may be inappropriate if you use variable cell rows.
This is category for NSString that creates string of empty spaces that will create space for your custom button and second will generate bitmap image that will be placed as background pattern image. For parameters you must set text attributes for original title, that is basically @{NSFontAttributeName: [UIFont systemFontOfSize:18]}
, than your desired text attributes. Maybe there is better way to achieve this :)
@implementation NSString (WhiteSpace)
- (NSString *)whitespaceReplacementWithSystemAttributes:(NSDictionary *)systemAttributes newAttributes:(NSDictionary *)newAttributes
{
NSString *stringTitle = self;
NSMutableString *stringTitleWS = [[NSMutableString alloc] initWithString:@""];
CGFloat diff = 0;
CGSize stringTitleSize = [stringTitle sizeWithAttributes:newAttributes];
CGSize stringTitleWSSize;
NSDictionary *originalAttributes = systemAttributes;
do {
[stringTitleWS appendString:@" "];
stringTitleWSSize = [stringTitleWS sizeWithAttributes:originalAttributes];
diff = (stringTitleSize.width - stringTitleWSSize.width);
if (diff <= 1.5) {
break;
}
}
while (diff > 0);
return [stringTitleWS copy];
}
@end
Second important part is code that renders bitmap that can be used as pattern image for UITableViewRowAction's backgroundColor.
- (UIImage *)imageForTableViewRowActionWithTitle:(NSString *)title textAttributes:(NSDictionary *)attributes backgroundColor:(UIColor *)color cellHeight:(CGFloat)cellHeight
{
NSString *titleString = title;
NSDictionary *originalAttributes = @{NSFontAttributeName: [UIFont systemFontOfSize:18]};
CGSize originalSize = [titleString sizeWithAttributes:originalAttributes];
CGSize newSize = CGSizeMake(originalSize.width + kSystemTextPadding + kSystemTextPadding, originalSize.height);
CGRect drawingRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, cellHeight));
UIGraphicsBeginImageContextWithOptions(drawingRect.size, YES, [UIScreen mainScreen].nativeScale);
CGContextRef contextRef = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(contextRef, color.CGColor);
CGContextFillRect(contextRef, drawingRect);
UILabel *label = [[UILabel alloc] initWithFrame:drawingRect];
label.textAlignment = NSTextAlignmentCenter;
label.attributedText = [[NSAttributedString alloc] initWithString:title attributes:attributes];
[label drawTextInRect:drawingRect];
//This is other way how to render string
// CGSize size = [titleString sizeWithAttributes:attributes];
// CGFloat x = (drawingRect.size.width - size.width)/2;
// CGFloat y = (drawingRect.size.height - size.height)/2;
// drawingRect.origin = CGPointMake(x, y);
// [titleString drawInRect:drawingRect withAttributes:attributes];
UIImage *returningImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return returningImage;
}
And then when you are creating your row action you can do something like this:
NSDictionary *systemAttributes = @{ NSFontAttributeName: [UIFont systemFontOfSize:18] };
NSDictionary *newAttributes = @{NSFontAttributeName: [UIFont fontWithName:@"Any font" size:15]};
NSString *actionTitle = @"Delete";
NSString *titleWhiteSpaced = [actionTitle whitespaceReplacementWithSystemAttributes:systemTextFontAttributes newAttributes:newAttributes];
UITableViewRowAction *rowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:titleWhiteSpaced handle:NULL];
UIImage *patternImage = [self imageForTableViewRowActionWithTitle:actionTitle textAttributes:newAttributes backgroundColor:[UIColor redColor] cellHeight:50];
rowAction.backgroundColor = [UIColor colorWithPatternImage:patternImage];
This solution is obviously hacky but you can achieve desired results without using private APIs and in future if something breaks, this will not break your app. Only button will look inappropriate.
Example of result:
This code has of course a lot of space for improvements, any suggestions are appreciated.

- 1,685
- 17
- 26
I'm afraid that there's no way to change the title color of the UITableViewRowAction.
The only things you can change on the action are:
- backgroundColor
- style (destructive (red backgroundcolor, ...)
- title
For more info, please refer to the Apple Doc UITableViewRowAction

- 6,075
- 2
- 32
- 35
-
1I checked that even. But still, I would like to know is there any other way of customising it. Thank you in advance. – GJDK Nov 12 '14 at 13:33
-
See my answer below that relies on UITableViewRowAction being a UIButton. There is indeed a way. – ToddB May 06 '15 at 00:46
Swift
No need to mess with UIButton.appearance...
Put this in your cell's class and change UITableViewCellActionButton according to your needs.
override func layoutSubviews() {
super.layoutSubviews()
for subview in self.subviews {
for subview2 in subview.subviews {
if (String(subview2).rangeOfString("UITableViewCellActionButton") != nil) {
for view in subview2.subviews {
if (String(view).rangeOfString("UIButtonLabel") != nil) {
if let label = view as? UILabel {
label.textColor = YOUR COLOUR
}
}
}
}
}
}
}

- 798
- 7
- 28
-
You could also configure the button's label one level above, instead of `for view in subview2.subviews`, something like `if let button = subview2 as? UIButton { button.setTitleColor(yourColour, forState: .Normal) }`. Or `button.titleLabel?.font = yourCustomFont` :] – Rygen Apr 01 '16 at 11:33
-
-
2@HassanTaleb I just tried this in Xcode 9 in iOS 11 simulator and this hack no longer works. So updating to Swift 4 isn't going to help you much. – jhelzer Jul 13 '17 at 17:13
So there still is no public api to change textColor
or font
to the cells action in the iOS 13 days.
Working solution for Swift 5.3, iOS 14
Hacks from answers in the thread have very unreliable results but I have managed to get my version of the hack working.
1. Getting the label
Here is my simplified way of accessing the actions UILabel
:
extension UITableViewCell {
var cellActionButtonLabel: UILabel? {
superview?.subviews
.filter { String(describing: $0).range(of: "UISwipeActionPullView") != nil }
.flatMap { $0.subviews }
.filter { String(describing: $0).range(of: "UISwipeActionStandardButton") != nil }
.flatMap { $0.subviews }
.compactMap { $0 as? UILabel }.first
}
}
2. Updating the label on layout changes
Next, overriding layoutSubviews()
in my UITableViewCell
subclass wasn't enough so additionally I had to override layoutIfNeeded()
for the hack to work.
Note that it's important to override both of them!
override func layoutSubviews() {
super.layoutSubviews()
cellActionButtonLabel?.textColor = .black // you color goes here
}
override func layoutIfNeeded() {
super.layoutIfNeeded()
cellActionButtonLabel?.textColor = .black // you color goes here
}
3. Triggering extra layout refresh
The last piece of the puzzle is to schedule an additional refresh of the color, so we cover all of those cases where for some reason above functions would not get called. The best place for doing so is UITableViewDelegate
method ..., willBeginEditingRowAt: ...
func tableView(_ tableView: UITableView, willBeginEditingRowAt indexPath: IndexPath) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
tableView.cellForRow(at: indexPath)?.layoutIfNeeded()
}
}
A delayed layout refresh trigger does the trick of letting the UIKit configure the cell first, so we can jump right after with the customisation. 0.01
was just enough for me but i can probably vary from case to case.
4. Profit
Now you can customise the label anyway you want! Change the text, its color, font or add a subview!
It goes without saying that this can break -anytime- if Apple will decide to change their private implementation.

- 3,749
- 1
- 20
- 34
-
Thank you for sharing this. I have adopted your solution and can confirm that it is working (Swift 5.3, Xcode 12.2)... still I am confused that you cannot "officially" change the text color, especially when supporting dark mode in an app. – Christian Nov 27 '20 at 09:33
-
There is a lot of things in UIKit that I wish would be customisable, but unfortunately apple left us with nothing in many cases. – Witek Bobrowski Nov 27 '20 at 09:36
-
Seemed promising but it does not really work. With Swift 5, it causes text color to revert to the default color when quickly swiping the same cell multiple times. Also, I noticed this does not change a second UIContextualAction text color. – Michael Colonna Dec 31 '20 at 01:47
-
-
@Bagusflyer its only nil in the default state of the cell, put on a breakpoint on the line when you call it and the swipe the cell. It will return a proper value. I have just tested that on Xcode 12.4 – Witek Bobrowski Feb 05 '21 at 10:05
There is indeed a way to change the title color of the UITableViewRowAction. It's a button. You can use the UIButton
appearance proxy:
[[UIButton appearance] setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];

- 2,490
- 3
- 23
- 40
-
Thanks, This is working for me. I have done below code UITableViewRowAction *button = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@" " handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) { NSLog(@"Action to perform with Button 1"); }]; button.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"XYZ_PNG"]]; [[UIButton appearance] setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; – Devil Feb 01 '15 at 09:15
-
4This is a fun trick, but it changes the appearance for ALL UIButtons from then on. As a result, the results are often undesirable as many other buttons in your UI are changed. – MobileVet Sep 01 '15 at 19:01
-
1if i have 2 buttons and need 2 differents color for each, how work this? – jose920405 Sep 16 '15 at 21:18
-
-
@MobileVet The results may not suit all applications, but it is exactly the behavior that my application requires. For me it is more than a fun trick. – ToddB Sep 17 '15 at 13:57
Lee Andrew's answer in Swift 3 / Swift 4:
class MyCell: UITableViewCell {
override func layoutSubviews() {
super.layoutSubviews()
for subview in self.subviews {
for sub in subview.subviews {
if String(describing: sub).range(of: "UITableViewCellActionButton") != nil {
for view in sub.subviews {
if String(describing: view).range(of: "UIButtonLabel") != nil {
if let label = view as? UILabel {
label.textColor = UIColor.black
}
}
}
}
}
}
}
}

- 16,783
- 19
- 105
- 136
-
-
-
1okay will do within the next 72 hours. need to get xcode 9 first. on my way across the earth right now. will do as soon as i have decent wifi @HassanTaleb – David Seek Jun 10 '17 at 13:06
-
1Using String(describing: sub) for identification is not that reliable since Apple, or event your colleage, can change an object's describing anytime. Read more about [String.init(describing:)](https://developer.apple.com/documentation/swift/string/2427941-init) Here is the [case](https://nshipster.com/apns-device-tokens/#overturned-in-ios-13) that Apple has changed the description of NSData. – Michael Revlis Oct 23 '19 at 02:50
-
Of course it's not perfect. But as there is no API that's the way we have to do it to have a workaround and be able to accomplish our goal. – David Seek Oct 23 '19 at 20:02
iOS 11 solution:
Create UITableViewCell
extension like this:
extension UITableViewCell {
/// Returns label of cell action button.
///
/// Use this property to set cell action button label color.
var cellActionButtonLabel: UILabel? {
for subview in self.superview?.subviews ?? [] {
if String(describing: subview).range(of: "UISwipeActionPullView") != nil {
for view in subview.subviews {
if String(describing: view).range(of: "UISwipeActionStandardButton") != nil {
for sub in view.subviews {
if let label = sub as? UILabel {
return label
}
}
}
}
}
}
return nil
}
}
And write this in your UITableViewCell
override func layoutSubviews() {
super.layoutSubviews()
cellActionButtonLabel?.textColor = .red
}
But there is a bug - if you pull the cell fast this code sometimes doesn't change the color.

- 1,999
- 2
- 21
- 28
You can add these two functions in your UITableViewCell
subclass and call the setActionButtonsTitleColor
function to set action buttons' title color.
func setActionButtonsTitleColor(color: UIColor) {
let actionButtons: [UIButton] = self.getActionButtons()
for actionButton in actionButtons {
actionButton.setTitleColor(color, for: .normal)
}
}
func getActionButtons() -> [UIButton] {
let actionButtons: [UIButton] = self.subviews.map {
(view: UIView) -> [UIView] in
return view.subviews
}
.joined()
.filter {
(view: UIView) -> Bool in
return String(describing: view).contains("UITableViewCellActionButton")
}.flatMap {
(view: UIView) -> UIButton? in
return view as? UIButton
}
return actionButtons
}

- 11
- 2
Thanks @Witek for sharing.
Your solution works but it's not stable. So, I try to update your code, and now it's working very well.
Put this code below in your UITableViewCell
override func layoutSubviews() {
super.layoutSubviews()
if let button = actionButton {
button.setTitleColor(.black, for: .normal)
}
}
override func layoutIfNeeded() {
super.layoutIfNeeded()
if let button = actionButton {
button.setTitleColor(.black, for: .normal)
}
}
var actionButton: UIButton? {
superview?.subviews
.filter({ String(describing: $0).range(of: "UISwipeActionPullView") != nil })
.flatMap({ $0.subviews })
.filter({ String(describing: $0).range(of: "UISwipeActionStandardButton") != nil })
.compactMap { $0 as? UIButton }.first
}

- 21
- 3
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewRowAction *editAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"edit" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
{
// Action something here
}];
editAction.backgroundColor = [UIColor whiteColor];
[[UIButton appearance] setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
return @[editAction];
-
"[[UIButton appearance] setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];" code change your all button text color which are in the app – Bijender Singh Shekhawat Apr 14 '18 at 12:10
IF someone is still looking for an alternative solution:
You can use the swipecellkit pod
https://github.com/SwipeCellKit/SwipeCellKit
This lets you customize the label color, image color and even the entire background while perserving the actual look and feel of the native implementation.

- 1
- 3