首页 > 其他分享 >详解 CALayer 和 UIView 的区别和联系

详解 CALayer 和 UIView 的区别和联系

时间:2023-02-02 22:32:02浏览次数:61  
标签:动画 Layer layer 详解 CALayer UIView View


前言


前面发了一篇iOS 面试的文章,在说到 UIView 和 CALayer 的区别和联系的时候,被喵神指出没有切中要点,所以这里就 CALayer 和 UIView 这个问题重新整理了下。这里会先分条解释,最后会在文章的结尾给出概括性总结。

1.首先UIView可以响应事件,Layer不可以.

UIKit使用UIResponder作为响应对象,来响应系统传递过来的事件并进行处理。UIApplication、UIViewController、UIView、和所有从UIView派生出来的UIKit类(包括UIWindow)都直接或间接地继承自UIResponder类。

在 UIResponder中定义了处理各种事件和事件传递的接口, 而 CALayer直接继承 NSObject,并没有相应的处理事件的接口。

下面列举一些处理触摸事件的接口

  • – touchesBegan:withEvent:
  • – touchesMoved:withEvent:
  • – touchesEnded:withEvent:
  • – touchesCancelled:withEvent:

其实还有一些运动和远程控制事件等等,这里就不一一列举了。

下面的两篇文章详细介绍了 iOS 事件的处理和传递

参考链接:

2.View和CALayer的Frame映射及View如何创建CALayer.

一个 Layer 的 frame 是由它的 anchorPoint,position,bounds,和 transform 共同决定的,而一个 View 的 frame 只是简单的返回 Layer的 frame,同样 View 的 center和 bounds 也是返回 Layer 的一些属性。(PS:center有些特列)为了证明这些,我做了如下的测试。

首先我自定义了两个类CustomView,CustomLayer分别继承 UIView 和 CALayer

在 CustomView 中重写了

+ (Class)layerClass
{
return [CustomLayer class];
}
- (void)setFrame:(CGRect)frame
{
[super setFrame:frame];
}
- (void)setCenter:(CGPoint)center
{
[super setCenter:center];
}
- (void)setBounds:(CGRect)bounds
{
[super setBounds:bounds];
}



同样在 CustomLayer中同样重写这些方法。只是 setCenter方法改成setPosition方法

我在两个类的初始化方法中都打下了断点


详解 CALayer 和 UIView 的区别和联系_html

首先我们会发现,我们在 [view initWithFrame] 的时候调用私有方法【UIView _createLayerWithFrame】去创建 CALayer。

然后我在创建 View 的时候,在 Layer 和 View 中Frame 相关的所有方法中都加上断点,可以看到大致如下的调用顺序如下

[UIView _createLayerWithFrame]
[Layer setBounds:bounds]
[UIView setFrame:Frame]
[Layer setFrame:frame]
[Layer setPosition:position]
[Layer setBounds:bounds]


我发现在创建的过程只有调用了 Layer 的设置尺寸和位置的然而并没有调用View 的 SetCenter 和 SetBounds 方法。

然后我发现当我修改了 view的 bounds.size 或者 bounds.origin 的时候也只会调用上边 Layer的一些方法。所以我大胆的猜一下,View 的 Center 和 Bounds 只是直接返回layer 对应的 Position 和 Bounds.

View中frame getter方法,bounds和center,UIView并没有做什么工作;它只是简单的各自调用它底层的CALayer的frame,bounds和position方法。

关于 Frame 的理解参考:​​http://www.cocoachina.com/industry/20131209/7498.html​

3.UIView主要是对显示内容的管理而 CALayer 主要侧重显示内容的绘制。

我在 UIView 和 CALayer 分别重写了父类的方法。

[UIView drawRect:rect]//UIView    
[CALayer display]//CALayer

然后我在上面两个方法加了断点,可以看到如下的执行。


详解 CALayer 和 UIView 的区别和联系_处理事件_02

可以看到 UIView 是 CALayer 的CALayerDelegate,我猜测是在代理方法内部[UIView(CALayerDelegate) drawLayer:inContext]调用 UIView 的 DrawRect方法,从而绘制出了 UIView 的内容.

4.在做 iOS 动画的时候,修改非 RootLayer的属性(譬如位置、背景色等)会默认产生隐式动画,而修改UIView则不会。

对于每一个 UIView 都有一个 layer,把这个 layer 且称作RootLayer,而不是 View 的根 Layer的叫做 非 RootLayer。我们对UIView的属性修改时时不会产生默认动画,而对单独 layer属性直接修改会,这个默认动画的时间缺省值是0.25s.

在 Core Animation 编程指南的 “How to Animate Layer-Backed Views” 中,对为什么会这样做出了一个解释:

UIView 默认情况下禁止了 layer 动画,但是在 animation block 中又重新启用了它们

是因为任何可动画的 layer 属性改变时,layer 都会寻找并运行合适的 'action' 来实行这个改变。在 Core Animation 的专业术语中就把这样的动画统称为动作 (action,或者 CAAction)。

layer 通过向它的 delegate 发送 actionForLayer:forKey: 消息来询问提供一个对应属性变化的 action。delegate 可以通过返回以下三者之一来进行响应:

  1. 它可以返回一个动作对象,这种情况下 layer 将使用这个动作。
  2. 它可以返回一个 nil, 这样 layer 就会到其他地方继续寻找。
  3. 它可以返回一个 NSNull 对象,告诉 layer 这里不需要执行一个动作,搜索也会就此停止。

当 layer 在背后支持一个 view 的时候,view 就是它的 delegate;

这部分的具体内容参考:​​http://objccn.io/issue-12-4/​

总结

总接来说就是如下几点:

  • 每个 UIView 内部都有一个 CALayer 在背后提供内容的绘制和显示,并且 UIView 的尺寸样式都由内部的 Layer 所提供。两者都有树状层级结构,layer 内部有 SubLayers,View 内部有 SubViews.但是 Layer 比 View 多了个AnchorPoint
  • 在 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
  • 两者最明显的区别是 View可以接受并处理事件,而 Layer 不可以

参考链接

作者:​​@武蕴牛x​​ 授权本站转载。

标签:动画,Layer,layer,详解,CALayer,UIView,View
From: https://blog.51cto.com/u_15952281/6034004

相关文章

  • stream操作常用API 示例详解
    简介从JDK8开始,增加了一新特性Stream流式操作,Stream中提供了非常多的API供大家使用,灵活的使用这些API,可以非常的方便且优美的实现我们的代码逻辑。最终型toArraytoArray......
  • 反向传播与梯度下降详解
    一,前向传播与反向传播1.1,神经网络训练过程神经网络训练过程是:先通过随机参数“猜“一个结果(模型前向传播过程),这里称为预测结果$a$;然后计算$a$与样本标签值$y$的差......
  • Linux 路由表详解
    一、查看路由表[root@VM_139_74_centos~]#routeKernelIProutingtableDestinationGatewayGenmaskFlagsMetricRefUseIfacedefault......
  • Kroger EDI 850 采购订单报文详解
    本文着重讲述KrogerEDI项目中,Kroger发给供应商的X12850报文(采购订单)。在此前的文章 如何读懂X12 中,我们对X12已经做了详细的解读,接下来让我们以KrogerEDI项目中对X......
  • Python内置函数详解-总结篇
     一直以来都是现查现学Python的相关内置函数,想看看全部的汇总版本,最近还真发现有大佬早已把相关的内置函数全部汇总完毕了。博主十月狐狸将Python3.5版本中的68......
  • bootstrap suggest搜索建议插件使用详解
    近日因工作需要看了下此插件。首先下载bootstrapjs包。添加此插件的引用。注意css样式要引用,不能忘记。前台页面代码,因为楼主做的是选项卡切换查询不同的结果。......
  • mysql索引详解
    本文转载自https://javaguide.cn/database/mysql/mysql-index.html索引介绍索引是一种用于快速查询和检索数据的数据结构,其本质可以看成是一种排序好的数据结构。索引......
  • nginx 日志分析之 access.log 格式详解
    说明:access.log的格式是可以自己自定义,输出的信息格式在nginx.conf中设置一般默认配置如下:http{...log_formatmain'$remote_addr-$remote_user[$time_lo......
  • JavaScript的this指向详解
    一、概念:函数的上下文(this)由调用函数的方式决定,function是“运行时上下文”策略;函数如果不调用,则不能确定函数的上下文。二、规则:对象打点调用它的方法函数,......
  • 博奥智源,老师定位分析仪软件功能开发详解
    1.采用B/S架构设计,支持通用浏览器进行远程访问进行管理;2.采用图像识别定位分析技术,智能识别教学行为,根据预设的跟踪分析逻辑触发跟踪信号,与录播主机进行跟踪数据对接;3.......