CALayer - Shadow causes a performance hit?
Solution 1
You should expect a slowdown from adding a shadow. A shadowRadius
of 20 is very high and will be especially slow.
The other key to improve shadow rendering speed: set the shadowPath
property. It can help dramatically.
Solution 2
self.view.layer.shouldRasterize = YES;
self.view.layer.rasterizationScale = UIScreen.mainScreen.scale;
I was recently having some issues with slow CALayer shadows, and that simple line of code fixed up everything for me!
Solution 3
Using shadowPath
instead of shadowOffset
.
theView.layer.shadowPath = [UIBezierPath bezierPathWithRect:theView.bounds].CGPath;
Check this post: iphone - Animation's performance is very poor when view's shadow is on
Solution 4
Yes, shadow's are very expensive (especially a shadow that big -- play with the radius and you'll notice it makes a huge difference in the degree of slowdown you experience). One way to improve performance is to render it once to a CGImageContext
and just display that image instead of having the layer re-render the shadow every time it redraws (but this doesn't work if the shadow needs to animate or something).
Related videos on Youtube
aryaxt
Updated on May 11, 2021Comments
-
aryaxt about 3 years
So I am doing some custom animations on my navigationcontroller and the way it pushes and pops the viewControllers.
Everything runs smooth. As soon as I add the following code (In a subclass of
UINavigationController
), I face a huge performance hit. After adding a shadow all animations become very laggy. Is this expected or am I doing something wrong in the code?// This code gets called once during NavigationController initialization. [self.view setClipsToBounds:NO]; [self.view.layer setCornerRadius:5]; [self.view.layer setShadowOffset:CGSizeMake(0, 20)]; [self.view.layer setShadowColor:[[UIColor yellowColor] CGColor]]; [self.view.layer setShadowRadius:20.0]; [self.view.layer setShadowOpacity:1];
EDIT:
Changed my shadow radius to 1 and it's still slow
-
Chris Conover about 10 yearsFor all it's worth, this is covered explicitly in WWDC 2010 Session 425: Core Animation in Practice, Part 2 here.
-
-
aryaxt about 12 yearsYou think it would perform better to use an actual png and add it to my UIView?
-
Ian Henry about 12 yearsIf that's a possibility (ie you know the shape/size/whatever of the shadow beforehand) then it would definitely give you better performance. Blitting images is much faster than rendering shadows.
-
aryaxt about 12 yearssetting ShadowPath did the trick, My shadow radius is 10 and it still performs well.
-
aryaxt about 12 yearsawesome, this makes it perform even better, now I can have any size of shadowRadius without having a performance hit
-
aryaxt over 11 years@NicolasManzini More tips for shadow performance: stackoverflow.com/questions/10133109/…
-
Sean over 11 yearsThis will ignore the retina images that you may have for you annotation. To fix this, add the following line: self.view.layer.rasterizationScale = [UIScreen mainScreen].scale;
-
Alfie Hanssen almost 11 yearsI'm having a similar issue with a tableView where each cell contains a few UILabels as well as a view with rounded corners. I added a shadow to the layer that contains the tableView and the scrolling becomes choppy. However, setting shouldRasterize = YES resolved the choppiness but pixelated the view (visibly blurry) so it's not an acceptable solution. I found using shadowPath instead of shadowOffset did the trick.
-
Alfie Hanssen almost 11 yearsWorked like a charm, better than shouldRasterize which blurred the view and all sublayers.
-
Denis Kozhukhov over 10 yearsit's much efficient way that I test... idea with shouldRasterize work not so quick as it can be needed. this answer is much better! don't understand why @williamcotton answer gain so much votes...
-
Denis Kozhukhov over 10 yearsit's much efficient way that I test... idea with shouldRasterize work not so quick as it can be needed. this answer is much better! don't understand why @williamcotton answer gain so much votes...
-
Liam almost 10 yearsshadowPath did the trick. performance feels a million times better!
-
ikzjfr0 over 9 yearsit could be worse if the view varies. shouldRasterize = YES is only a good solution when the view does not change, so bitmap is genereated once once and cached and reused by UIScrollView
-
TomSawyer over 9 yearsshadowPath is pretty good and fast, but how can keep update frame in autolayout?
-
Maciej Swic over 9 yearsPlease note that this increases your RAM usage
-
chakrit about 9 yearsThis is only if you don't have rounded corners or transparency in your views. Not every views is rectangular.
shouldRasterize
is more generic and we don't have to deal with any bezier paths as said. -
Andres Canella almost 8 yearsPrerendered to an image will work as long as yuo don't need to change the shadow shape.
-
Nelly v almost 8 yearsAwesome! Exactly what I was after! Thank you.
-
ooops over 7 years@TomSawyer do it in view's layoutSubviews, maybe you need subclass some views