iOS - UIView vs CALayer
前言
在核心动画iOS - 核心动画初探文章中提到了CoreAnimation是直接作用在CALayer
上的,并非UIView
。那为什么不是直接作用在UIView上的呢?既然有了UIView,为什么还会有CALayer的存在呢?它们之间到底有着怎样的联系呢?
UIView与CALayer并存
苹果为何要如此设计?
为何不用一个简单的层级来处理所有的事情,其实原因在于职责分明
,这样可以避免很多重复代码,在iOS
和Mac OS
两个平台下,事件和用户交互存在较大的差异,比如Mac OS 的用户交互可以通过鼠标
、键盘
控制。
而iOS则通过手势触摸
,这就是为何iOS开发界面使用UIKit
和UIView
,而Mac OS 开发界面使用AppKit
和 NSView
。因为他们之间的用户交互手段不一样,但是它们在功能上是非常相似的,所以都有CALayer
,而CALayer
显示上的需求,不做交互上的需求处理,这样设计就可以减少非常多的不必要代码。
- 首先UIView可以响应事件,CALayer不可以。UIKit使用
UIResponder
来响应事件,UIView继承于UIResponder
,而CALayer继承自NSObject
,不可响应事件。 - UIView是CALayer的
delegate
. - 一个Layer的frame是由它的
anchorPoint
,position
,bounds
,和transform
共同决定的,而一个View的frame只是简单的返回Layer的frame
,View的Center
和Bounds
只是直接返回layer对应的Position
和Bounds
。 - UIView依赖CALayer提供的内容,CALayer依赖UIView提供的
容器
来显示绘制的内容。归根到底CALayer是这一切的基础
,如果没有CALayer,UIView自身也不会存在,UIView是一个特殊的CALayer实现,添加了响应事件
的能力。
UIView001
但CALayer虽不能处理触摸事件,同样也有UIView不能做的事情:
1.
阴影、圆角、颜色边框
2.
3D变换
3.
非矩形范围
4.
透明遮罩
5.
多级非线性动画
所以CALayer有它存在的必要性,不同职责而已。
总结
每个UIView内部都有一个CALayer在背后提供内容的绘制和显示
,并且UIView的尺寸样式都由内部的Layer所提供,Layer比View多了个AnchorPoint
。两者都是树状层级结构,layer内部有SubLayers
,View 内部有 SubViews
。
在View显示的时候,UIView 做为 Layer 的CALayerDelegate
,View的显示内容取决于内部的 CALayer的display
。
CALayer是默认修改属性支持隐式动画
的,在给UIView的Layer做动画的时候,View作为Layer的代理,Layer通过actionForLayer:forKey:
向View请求相应的action
(动画行为
)。
layer内部维护着三份layer tree
,分别是 presentLayer Tree
(动画树
), modeLayer Tree
(模型树
), Render Tree
(渲染树
),在做 iOS动画的时候,我们修改动画的属性,在动画的其实是Layer的 presentLayer
的属性值
, 而最终展示在界面上的其实是提供View的modelLayer
。
![](https://img.haomeiwen.com/i4469396/e26f2da09c71a7e8.png)
![](https://img.haomeiwen.com/i4469396/108c3157d3dcc990.png)