题 CALayer - 暗影导致性能下降?


所以我在我的navigationcontroller上做一些自定义动画以及它推送和弹出viewControllers的方式。

一切顺利。只要我添加以下代码(在。的子类中) UINavigationController),我面临巨大的性能打击。添加阴影后,所有动画都变得非常迟钝。这是预期的还是我在代码中做错了什么?

// 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];

编辑:

将我的阴影半径更改为1,它仍然很慢


28
2018-04-03 17:02


起源


尽管如此,WWDC 2010 Session 425:Core Animation in Practice,Part 2中明确涵盖了这一点 这里。 - Chris Conover


答案:


您应该期望通过添加阴影来减速。一个 shadowRadius 20是非常高,将特别慢。

另一个提高阴影渲染速度的关键:设置 shadowPath 属性。它可以帮助戏剧性。


42
2018-04-03 17:15



设置ShadowPath就可以了,我的阴影半径是10,它仍然表现良好。 - aryaxt
刚救了我的命:) - Nicolas Manzini
@NicolasManzini有关阴影表现的更多提示: stackoverflow.com/questions/10133109/... - aryaxt
这是一种非常有效的方式,我测试...使用shouldRasterize工作的想法不是那么快就需要它。这个答案要好得多!不明白为什么@williamcotton回答得到这么多票... - Denis Kozhukhov
设置ShadowPath就可以了,但为什么呢? - ikzjfr0


self.view.layer.shouldRasterize = YES;
self.view.layer.rasterizationScale = UIScreen.mainScreen.scale;

我最近遇到了缓慢的CALayer阴影的一些问题,而那简单的代码行为我修复了一切!


81
2018-04-30 18:14



真棒,这使它表现得更好,现在我可以拥有任何大小的shadowRadius而不会有性能损失 - aryaxt
这将忽略您可能为您注释的视网膜图像。要解决此问题,请添加以下行:self.view.layer.rasterizationScale = [UIScreen mainScreen] .scale; - Sean
我在tableView中遇到类似的问题,其中每个单元格包含一些UILabel以及带圆角的视图。我在包含tableView的图层中添加了一个阴影,滚动变得不稳定。然而,设置shouldRasterize = YES解决了波动,但像素化视图(明显模糊),所以这不是一个可接受的解决方案。我发现使用shadowPath而不是shadowOffset就可以了。 - Alfie Hanssen
像沙姆一样工作 - Johannes
如果观点不同,可能会更糟。当视图没有改变时,shouldRasterize = YES只是一个很好的解决方案,因此位图一次生成一次并由UIScrollView缓存和重用 - ikzjfr0


运用 shadowPath 代替 shadowOffset

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

查看这篇文章: iphone - 当视图的阴影打开时,动画的性能非常差


13
2018-03-04 06:30



像魅力一样工作,比使用模糊视图和所有子层的应该更好。 - Alfie Hanssen
这是一种非常有效的方式,我测试...使用shouldRasterize工作的想法不是那么快就需要它。这个答案要好得多!不明白为什么@williamcotton回答得到这么多票... - Denis Kozhukhov
shadowPath相当不错,但是如何在autolayout中保持更新框架? - TomSawyer
仅当您的视图中没有圆角或透明度时才会这样。并非每个视图都是矩形的。 shouldRasterize 更通用,我们不必处理任何bezier路径。 - chakrit
@TomSawyer在视图的layoutSubviews中执行它,也许您需要子类化一些视图 - ooops


是的,阴影是非常昂贵的(特别是一个大的阴影 - 与半径一起玩,你会发现它会对你经历的减速程度产生巨大影响)。提高性能的一种方法是将其渲染一次 CGImageContext 并且只显示该图像而不是每次重绘时图层都重新渲染阴影(但如果阴影需要动画或其他东西,这不起作用)。


2
2018-04-03 17:09



您认为使用实际的png并将其添加到我的UIView会更好吗? - aryaxt
如果这是一种可能性(即你事先知道形状/大小/任何阴影)那么它肯定会给你更好的表现。 Blitting图像比渲染阴影快得多。 - Ian Henry
只要yuo不需要更改阴影形状,预渲染图像就会起作用。 - Andres Canella