I found an existing answer to this question, but was not satisfied. Here, an alternative approach requiring less code does not require overriding any methods and can be applied to any representation. The idea is to add a CAGradientLayer as a sublayer to the UIView layer. I could not find this approach anywhere, so I would like to share.
Add a CAGradientLayer to any UIView as follows:
The category in the UIView header is UIView + Gradient.h:
Category in UIView implementation of UIView + Gradient.m:
#import "UIView+Gradient.h" #import <QuartzCore/QuartzCore.h> @implementation UIView (Gradient) -(void) addLinearUniformGradient:(NSArray *)stopColors { CAGradientLayer *gradient = [CAGradientLayer layer]; gradient.frame = self.bounds; gradient.colors = stopColors; gradient.startPoint = CGPointMake(0.5f, 0.0f); gradient.endPoint = CGPointMake(0.5f, 1.0f); [self.layer addSublayer:gradient]; } @end
How to set gradient on UITableViewCell backgroundView after creating UITableViewCell :
This example shows how to set up a simple two-column gradient (with a uniform interval). A quick look at the CAGradientLayer documentation will show you how to adjust more complex gradients.
( * EDIT ADDITIONAL IMPORTANT INFORMATION * )
Another thing to keep in mind is that if you add a gradient layer in the tableView: cellForRowAtIndexPath method, UITableViewCells are usually reused (ie [tableView dequeueReusableCellWithIdentifier: @ "foo"]). Because cells are reused, if you always add a gradient layer to the table view cell every time a cell is unloaded, you can add several gradient layers to the tableview cell during the cell's lifetime. This can be a source of performance degradation. This problem can occur without any changes in the visible results, so it is difficult to detect / observe. There are several ways to solve this problem, but one thing you can consider is to modify the source code above in addition to adding a CAGradientLayer to return the created CAGradientLayer to the caller. Then itβs quite simple to write another category method that allows you to remove the gradient layer, if it is really contained in the view:
-(BOOL) removeGradient:(CAGradientLayer *)gradientLayer { // Search for gradient layer and remove it NSArray *layers = [self.layer sublayers]; for ( id layer in layers ) { if ( layer == gradientLayer ) { [gradientLayer removeFromSuperlayer]; return YES; } } // Failed to find the gradient layer in this view return NO; }
Gradient removal is not required for all use cases, but if your use case leads to cell reuse, you might want to remove the gradient. One place to consider this method is the UITableViewCell prepareForReuse method.
I apologize that my original solution did not address this issue. But since this is something that can be pretty subtle, I would like to update my answer with this additional information.