UIView和CALayer

发布时间:2026/7/15 13:58:06
UIView和CALayer 1 两者关系UIView来自UIKit框架继承自UIResponder可以响应和处理事件CALayer来自QuartzCore框架继承自NSObject负责绘制和展示内容。两者互相依赖UIView负责管理CALayer在add或remove时将其layer进行对应的处理是对CALayer的封装。分离开来是为了单一职责方便维护和拓展在Mac OS 平台上和UIView对应的是NSView这样就实现了复用。UIView的很多属性是依赖CALayer实现的比如frame\bounds\center\alpha\clipsToBounds最终调用了CALayer的frame\bounds\position\opacity\masksToBounds。而Layer的frame则依赖自身的anchorPotin、position、bounds和transform。比如UIView的alpha、hidden的获取和设置就是调用了CALayer的opacty和opaque。内容的绘制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 idCAAction)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];