Adding a drop shadow to NSString text in a drawRect: method without using UILabel

idStar picture idStar · Dec 8, 2010 · Viewed 14.3k times · Source

I'd like to add a drop shadow to text drawn using the iOS supplied NSString (UIStringDrawing) category method:

- (CGSize)drawAtPoint:(CGPoint)point forWidth:(CGFloat)width 
             withFont:(UIFont *)font minFontSize:(CGFloat)minFontSize 
       actualFontSize:(CGFloat *)actualFontSize 
        lineBreakMode:(UILineBreakMode)lineBreakMode
   baselineAdjustment:(UIBaselineAdjustment)baselineAdjustment; 

Clearly, there's no drop shadow option.

Yes, one could use a UILabel here and get drop shadow properties to set, but that wouldn't be as performant, since any UIView subclass (such as UILabel) wraps a CALayer object and is going to be heavier (performance wise).

Here's the context:

I'm doing custom drawing for a UITableViewCell subclass, implementing drawRect: on the table cell view instead of creating the table cell from a Nib file of composited UIView subclasses.

Compositing a bunch of UIView subclasses would defeat the purpose of trying to keep this lean and stay within 50-60 frames per second in table view scrolling performance.

I have tried drawing the string twice at a slight offset. This may turn out acceptable once I tweak the drop shadow color on the background color of the cell that I have going, but it seems rather kludgey. Certainly there's no drop shadow blur property like one gets with UILabel.

I searched for solutions and they either recommend UILabel usage (which I've dismissed per above, since I have about a dozen distinct textual elements getting composited on to the table cell view) or CGContextSetShadow(). The latter always seems to be suggested in the context of rectangular shapes, and not necessarily for attaching a shadow to the path of text drawn directly with the NSString drawAtPoint... method mentioned above. (I did try it, but it didn't seem to work (i.e. nothing changed); I'm new to Core Graphics drawing).

Suggestions?

Answer

Ole Begemann picture Ole Begemann · Dec 8, 2010

It works fine for me with CGContextSetShadow(). Example:

- (void)drawRect:(CGRect)rect 
{
    NSString *string = @"Hello World!";

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetShadow(context, CGSizeMake(20.0f, 20.0f), 10.0f);

    [string drawAtPoint:CGPointMake(100.0f, 100.0f) withFont:[UIFont boldSystemFontOfSize:36.0f]];
}