UIView和CALayer

Posted FarmGuo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UIView和CALayer相关的知识,希望对你有一定的参考价值。

1 两者关系

UIView来自UIKit框架,继承自UIResponder,CALayer来自QuartzCore框架,继承自NSObject。
两者互相依赖,UIView负责管理CALayer,在add或remove时,将其layer进行对应的处理,是对CALayer的封装,可以响应和处理事件。而CALyer则绘制和展示内容。
分离开来是为了单一职责,方便维护和拓展,在Mac OS 平台上,将UIView对应的是NSView,实现了复用。

UIView的很多属性是依赖CALayer实现的,比如frame\\bounds\\center\\alpha\\clipsToBounds,最终调用了气Layer的frame\\bounds\\position\\opacity\\masksToBounds。而Layer的frame则依赖自身的anchorPotin、position、bounds和transform。

比如UIView的alpha、hidden的获取和设置,就是调用了CALayer的opacty和hidden。

内容的绘制

UIView是CALayer的delgate,可以实现代理来参与内容等绘制,CALayerDelegate有以下可选方法:

@protocol CALayerDelegate <NSObject>
@optional
- (void)displayLayer:(CALayer *)layer;
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;
- (void)layerWillDraw:(CALayer *)layer
- (void)layoutSublayersOfLayer:(CALayer *)layer;
- (nullable id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event;

通过实现这些方法,UIView也可以来绘制内容。
-[UIView setNeedsDisplay]方法会标记内容需要更新,在下一个绘制周期到来时,内容会进行更新。
-[CALayer display],会调用delegate(即UIView)的-[UIView displayLayer:]方法。如果未实现,则调用-[CALayer drawInContext: ]。
-[CALayer drawInContext: ]会调用delegate的-[UIView drawLayer:inContext:]方法。
而默认的-[UIView drawLayer:inContext:]方法会尝试调用-[UIView drawRect:]方法。
调用顺序如下,自上而下,如果上面的实现了,则后面的不会被调用。

-[UIView displayLayer:]
-[UIView drawLayer:inContext:]
-[UIView drawRect:]

如果UIView通过重写上面其中一个方法即可参与内容的绘制。
UIView有个contentMode的属性,当设置为UIViewContentModeRedraw时,如果更新bound,也会导致内容更新。

对于自定义的View,通常会重写layoutSubviews方法,在里面更新subview的位置,但这个方法不应该直接调用,而是调用-[UIView setNeedsLayout]或-[UIView layoutIfNeeded],等待系统来更新layout。
前者设置一个标记,等待runloop的下一个周期,进行更新。
后者看是否有更新标记,有则立刻更新,否则直接返回。
所有需要立即更新就这样调用:

-[UIView setNeedsLayout];
-[UIView layoutIfNeeded];

以上是关于UIView和CALayer的主要内容,如果未能解决你的问题,请参考以下文章

使用 UIView 或 CALayer 绘制和动画?

iOS 中 UIView 和 CALayer 的关系

UIView和CALayer

UIView和CALayer

iOS开发之UIView和CALayer的区别

CALayer和UIView上的区别图