Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Added a shadow to a UIImageView on a UITableView kills performance... why?

I have a UITableView that has three UIImageView views per cell, with three cell displaying on the view at one time (for a total of nine UIImageView views). Think of it as a bookshelf. Sometimes I can have as many as 500 books.

I've added shadow to the UIImageView with code that is this:

UIImageView *itemImageView = [[UIImageView alloc] initWithFrame:CGRectMake(25, 7, 65, 75)];
itemImageView.contentMode = UIViewContentModeScaleAspectFit;
itemImageView.tag = 6;
itemImageView.layer.shadowColor = [UIColor blackColor].CGColor;
itemImageView.layer.shadowOffset = CGSizeMake(3, -1);
itemImageView.layer.shadowOpacity = 0.7;
itemImageView.layer.shadowRadius = 3.0;
itemImageView.clipsToBounds = NO;
[cell.contentView addSubview:itemImageView];

When I add the shadow code, as seen above, scrolling performance is just totally killed and becomes choppy. Each image has a different Rect so the shadow has to be created for each item as it scrolls. Anyone have any tips on how to add shadows to my images on a UITableView without having this issue?

like image 849
Ethan Allen Avatar asked Mar 29 '12 19:03

Ethan Allen


4 Answers

You may see a performance improvement if you add

itemImageView.layer.shadowPath =
       [UIBezierPath bezierPathWithRect:itemImageView.layer.bounds].CGPath;

But in general, layer operations like this will kill performance in a table view. I experienced exactly the same issue, and we just eliminated the shadow effect. It wasn't worth it.

like image 89
Mark Granoff Avatar answered Oct 24 '22 00:10

Mark Granoff


You should review the WWDC videos on CoreAnimation best practices. You can request that the rasterized copy of the shadow be cached in memory. Cocoa is definitely fast enough to render these shadows on the fly without falling back to a pre-rendered image.

Example:

itemImageView.layer.shouldRasterize = YES;

Also I up-voted the answer regarding UIBezierPath. This is also mentioned in the best practices, but setting the shadow path of a CALayer is a huge performance boost. You can also create some interesting special effects by manipulating the shadow path.

like image 42
Sam Avatar answered Oct 23 '22 23:10

Sam


Shadows are expensive and will kill your performance.

A better approach is to render the shadowed image in the background, cache/save it and display it on the view when its ready.

Edit: You way wish to look at Core Graphics / CGImage routines. Specifically CGContextSetShadowWithColor will draw you a shadow.

http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/CGContext/Reference/reference.html

like image 22
lorean Avatar answered Oct 24 '22 00:10

lorean


I have the same problem with adding shadow to labels inside a tableviewcell. I tried to layout the elements inside cellForRowAtIndexPath when the cell will be created:

if(cell == nil){
    //layout cell

These optimized the scrolling a little bit, but its quite choppy.

For optimizing your pictures quality you should add also the rasterizationScale if you activated "shouldRasterize":

aLabel.layer.shouldRasterize = YES;
aLabel.layer.rasterizationScale = [[UIScreen mainScreen] scale];

Maybe somebody has some ideas how to optimize the code to get the normal iOS scrolling. thx

like image 30
Alex Cio Avatar answered Oct 23 '22 22:10

Alex Cio