edwardmp edwardmp - 4 months ago 32
Objective-C Question

CALayer shadow in UITableViewCell Drawn incorrectly

I am applying shadow to a UITableViewCell using CALayer.

Here's my code:

- (void)addShadowToView:(UIView *)view
{
// shadow
view.layer.shadowColor = [[UIColor colorWithWhite:0.0f alpha:0.1f] CGColor];
view.layer.shadowOpacity = 1.0f;
view.layer.shadowOffset = CGSizeMake(0.0f, 3.0f);
view.layer.shadowRadius = 6.0f;

CGRect shadowFrame = view.layer.bounds;
CGPathRef shadowPath = [UIBezierPath bezierPathWithRect:shadowFrame].CGPath;
view.layer.shadowPath = shadowPath;
}


The issue is that for some tableviewcells, the shadow does not span the entire width of the cell. For some cells it would be correct, for others it would be faulty. I do notice that the rotation of the device also affects it, and reloading of the tableview data sometimes solves it.

What is the best way to mitigate this issue (and with that I don't mean to reload the whole tableview on each rotation etc.)?

Example bottom of cell where shadow is correctly applied:
enter image description here

Bottom of cell in same tableview after scrolling down (shadow only applied for first 75% of width):
enter image description here

Edit: I have noticed the issue is caused from these lines of code:

CGRect shadowFrame = view.layer.bounds;
CGPathRef shadowPath = [UIBezierPath bezierPathWithRect:shadowFrame].CGPath;
view.layer.shadowPath = shadowPath;


If I leave them out, everything is fine. But I've been told there is certain performance benefit when using this. Somehow the shadow is not correctly applied to new dimensions after rotating..

Answer

You can override the setter for you're cell's frame and call addShadowToView:. You can optimize this more by storing your cell's size and only updating the shadow path when the size changes for example:

@property (nonatomic, assign) CGSize size;

And

- (void) setFrame:(CGRect)frame
{
    [super setFrame:frame];
    // Need to check make sure this subview has been initialized
    if(self.subviewThatNeedsShadow != nil && !CGSizeEqualToSize(self.size,_frame.size)
    {
        [self addShadowToView: self.subviewThatNeedsShadow];
    }
}
Comments