coding with objc & swift

[译]设置阴影路径的重要性

| Comments

iOS上,给视图加上阴影很容易。只需要:

  1. 在项目中加上QuartzCore框架
  2. 在实现文件中import QuartzCore的头文件
  3. 加上这样的一行代码[myView.layer setShadowOpacity:0.5]

瞧!阴影加上了。

image

然而,最简单的方法通常都不是性能最好的方法。 如果你要用这个视图作动画(特别当它是一个UITableViewCell的一部分的时候),你可能会注意到动画的卡顿。这是因为在计算视图的阴影的时候,为了计算出到底应该怎么渲染视图的阴影,Core Animation需要做一个屏幕外的渲染通道(do an offscreen rendering pass)才能确定视图的形状。(记住,你的视图可能是任何一种复杂的图形,甚至它上面可能还带有孔洞)

为了证明这一点。现在打开模拟器,勾选上“调试”菜单中的“屏幕外渲染的颜色”选项。

image

或者,接上一个设备,启动Instruments(⌘I),选择Core Animation模板,选中Core Animation栏,勾上”Color Offscreen-Rendered Yellow”选项。

IMAGE

然后在模拟器上(或者设备上),你就会看到类似下面的这种东西:

IMAGE

这说明,某些东西正在强制的产生一个昂贵的屏幕外渲染通道。

快速修正的方法

幸运地是,修正这个阴影的性能问题和添加阴影的操作一样简单。你只需要告诉Core Animation你的视图是什么形状的就行了。用view.layer的setShadowPath:方法:

1
[myView.layer setShadowPath:[[UIBezierPath bezierPathWithRect:myView.bounds] CGPath]];

(注意:这里可能因为视图不同的形状,代码有所不同。UIBezierPath有许多方便的方法可以调用。比如如果你的视图有圆角,可以使用bezierPathWithRoundedRect:cornerRadius:方法。)

现在测试一下,用于指示屏幕外渲染内容的黄色区块应该消失了吧。

还要注意一点

每当你的视图的bounds变化后,你需要更新layer的阴影路径(shadowPath)。同样的,如果你做一个bounds变化的动画,你也需要给layer的阴影路径做一个动画来匹配bounds的变化。给layer的阴影路径做动画需要用到CAAnimation,因为UIView不能直接对shadowPath做动画(shadowPath是CALayer的属性)。用CAKeyframeAnimation可以很简单地对shadowPath做一个动画,只需要从一个CGPath变化到另一个CGPath就可以了。

原文: On the importance of setting shadowPath

Comments