CALayer和UIView的关系
# UIView
除负责相应事件(继承自UIResponder)外,它还是一个对CALayer的底层封装。可以说它们的相似行为都依赖于CALayer的实现,UIView只不过是封装了它的高级接口而已。
# CALayer
# 概念
图层(CALayer)的主要工作是管理您提供的可视内容,图层本身可以设置可视属性(例如背景颜色,边框和阴影)。除了管理可视内容外,还维护有关内容几何的信息(例如:位置,大小和变换),用于在屏幕上显示该内容。 管理基于图像内容的对象,允许您对该内容执行动画。继承自NSObject,不能够响应事件。
# CALayerDelegate
作用:
你可以使用delegate对象来提供图层的内容,处理任何子图层的布局,并提供自定义操作以响应与图层相关的更改。如果图层是由UIView创建的,则该UIView对象通常会自动指定为图层的委托。
注意:
- 在iOS中,如果图层与UIView对象关联,则必须将此属性设置为拥有该图层的UIView对象
- delegate只是另外一种为图层提供处理内容的方式,并不是唯一的,UIView的显示跟它图层委托没有太大关系。
# 代理方法
# displayLayer:
当图层标记为需要更新时,调用此方法,例如:为图层设置contents属性
# drawLayer:inContext
- 被drawInContext调用,可以使用CGContext来实现显示过程
- 和UIView的drawRect的关系
- 先调用CALayer的drawLayer:InContext
- 随后在super.drawLayer:InContext里面创建并配置好绘图环境
- 通过图层的super.drawLayer:InContext调用view的drawRect方法。注意:view的显示不依赖于UIGraphicsGetCurrentContext。只有在绘制的时候才需要。
- 和contents之间的关系: UIView的drawRect方法的所有绘制操作,都被保存在其图层的contents属性中,这也是为什么要CALayer提供绘图环境。
- 如果实现了displayLayer,此方法将不再调用
# layerwillDraw:
在drawLayer:inContext调用之前调用,可以使用此方法配置影响内容的任何图层状态(例如contentsFormat, isOpaque)
# layoutSublayersOfLayer:
和UIView的layoutSubviews类似,当发现边界发生变化并且其sublayers可能需要重新排列时(例如通过frame改变大小),将调用此方法
# actionForLayer:forKey:
CALayer之所以能够执行动画,是因为它被定义在CoreAnimation框架中,是CoreAnimation执行操作的核心。也就是说CALayer除了负责显示内容外,会能执行动画(其实是CoreAnimation与硬件之间的操作在执行,CALayer负责存储操作所需要的数据,相当于Model)。
# CALayer坐标系
UIView使用的所谓frame、bounds、center等属性,其实都是从CALayer中返回的,而frame只是CALayer中的一个计算型属性而已。
# anchorPoint
锚点是基于图层内部坐标的,取值范围(0-1,0-1),可以看作是bounds的缩放因子,中间的(0.5,0.5)是每个图层的anchorPoint默认值。而左上角的(0.0,0.0)被视为anchorPoint的起始点。任何基于图层的几何操作都是发生在锚点之上,例如:旋转。更改锚点位置,旋转会围绕新点旋转。
# position
锚点在父图层中的位置
position.x = frame.origin.x + anchorPoint.x*bounds.size.width
position.y = frame.origin.y + anchorPoint.y*bounds.size.height
2
anchorPoint和position之间的关系无论更改谁,对方都不会受影响,受影响的只会是frame.orgin
# frame
frame是一个计算属性,它是从bounds、anchorPoint和position的值中派生出来的。为此属性指定新值时,图层会更改其position和bounds属性以匹配您指定的矩形。
# 二者关系
layer影响视图变化,无论修改layer的可视内容或者几何信息,view都会跟着变化,反之亦是如此。证明:UIView依赖于CALayer得以显示
# 不同点
职责不同
- UIView的主要职责是负责接收并响应事件
- CALayer的主要职责是负责显示UI
需要复用
- 在macOS和App系统上,NSView和UIView虽然行为相似,在实现上却有着显著的区别,却都依赖于CALayer,在这种情况下,只能封装一个CALayer出来。
# 哪些是layer可以完成而view不行
阴影、圆角、彩色边框、3D变换、非矩形结构、透明mask以及非线性动画等