我依然爱iOS

UIView和CALayer的纠葛

2017-11-27  本文已影响19人  Cloudox_

我们都知道UIView和CALayer,即使不知道,平时的开发中也一定遇到过,比如要设置UIView的frame,利用view.layer来设置圆角等等,那这两者到底是什么关系?为什么又要有两个类来处理呢?

联系与区别

我们平时开发中总是直接去操作UIView更多一点,比如初始化一个UIView,设置它的属性如frame、背景色等等,但一些特殊时候,UIView的属性不够用了,就要用到其layer属性,来设置layer的属性,比如设置圆角、边框等。为什么不直接把这些属性给UIView呢?为什么UIView还有一个CALayer类型的属性呢?

其实,每个UIView,都会对应一个CALyaer,你再创建UIView的同时,也就创建了其对应的CALayer。我们印象里总觉得绘制一个控件是通过UIView来操作的,比如设置frame、center等等,但其实真正控制显示的,是CALayer,诸如UIView的frame、center等属性,只是直接引用了对应CALayer的frame、position等属性而已。

可能直观地说,我们看得见摸得着的一直都是UIView,但它之所以能够显示在界面上,全然是因为其背后的CALayer。创建UIView对象的时候,UIView内部会自动创建一个层(即CALayer对象),通过UIView的layer属性可以访问这个层。当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的层上,绘图完毕后,系统会将层拷贝到屏幕上,于是就完成了UIView的显示。UIView本身并不具备显示内容的能力,全都要靠CALayer来操作显示相关的内容。

那既然显示全靠CALayer,UIView有什么用?别忘了,控件除了可见以外,还有一个很重要的功能是响应事件。

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

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

·所以也就清晰了,两者虽然都是跟控件相关的,互相一一对应,但其实各司其职,真正控制显示的是CALayer,而接受事件并处理的是UIView。

为何不结合成一个类?

上面说明了二者的联系与区别,各司其职,那问题又来了,既然都是给控件服务的,为什么不干脆弄成一个类?叫UILayer之类的,岂不妙哉?

虽然把事情弄简单也是一种思路,但有时候还得考虑别的事情。在iOS的发展过程中,其实也是一个产品不断迭代的过程,而这个产品就是iOS的各种库。iOS的控件从可以显示,到能够响应多种事件处理,到支持block,到支持AutoLayout,到iOS7设计风格的变化与丰富,一直处于一个不断迭代变化的过程中,而并不是一个从一开始就设计好并且完美到从容面对各种更改的产物。

当我们自己开发一个不断更新迭代的产品的时候会如何做?而且产品的需求还总是变化,想象力无穷。要能够拥抱变化,最好就是让类简单、负责的事情少、各自继承自己的一套内容,负责界面的专心负责界面,负责事件响应的专门负责响应,要使用的时候,把两者结合一下就可以了,也就是最终的UIView中包含一个CALayer的属性,同时,也隐藏了很多CALayer的实现细节,只暴露出frame、动画等开发者需要的内容。此外,CALayer保持最基本的绘图机制不变,使其保持稳定,一些新增的变化,放在UIView中去实现,这样也可以增加系统的稳定性。

UIView和CALayer的纠葛是个可浅可深的问题,浅的来说就是一个负责事件响应一个负责显示的各司其职,往深了说,多问问为什么,就可以以小见大窥探大牛的设计思想,这也是非常重要的学习途径。


查看作者首页

参考:
http://www.cocoachina.com/ios/20150828/13244.html
http://www.cnblogs.com/chenhongios/p/4849559.html
http://www.cocoachina.com/ios/20150828/13257.html

上一篇下一篇

猜你喜欢

热点阅读