最近开始用思维导图工具,梳理一些知识点,但是长篇大论还是只能交给markdown。
1.UIView的绘制流程
上图的流程基本和https://blog.csdn.net/jingqiu880905/article/details/51851534/这里所说的一致。
我们发现drawRect:调用时机是比较靠后的,而且它会决定绘制流程的走向。重写了drawRect:也就意味着,layer会被调用setNeedDisplay方法。而drawRect:作为View层面暴露给使用者的绘制入口,是因为UIView实现了drawLayer:inContext:方法,它内部会调用drawRect:。
UIView作为layer的delegate,除了drawRect:外,还有两个绘制入口displayLayer:和drawLayer:inContext:。相比于drawRect:会自动被调用,后两者需要手动调用layer的setNeedDisplay方法才会被调用。
而layer层面,绘制入口只有drawInContext:,它的默认实现是调用delegate的drawLayer:inContext:方法。
关键测试代码如下:
@implementation MyLayer
- (void)drawInContext:(CGContextRef)ctx
{
NSLog(@"%s",__FUNCTION__);
[super drawInContext:ctx];
}
- (void)display
{
NSLog(@"%s",__FUNCTION__);
[super display];
}
- (void)setNeedsDisplay
{
NSLog(@"%s",__FUNCTION__);
[super setNeedsDisplay];
}
@end
@implementation MyView
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
//- (void)drawRect:(CGRect)rect {
// NSLog(@"%s",__FUNCTION__);
// [super drawRect:rect];
//}
+ (Class)layerClass
{
return MyLayer.class;
}
//- (void)displayLayer:(CALayer *)layer
//{
// NSLog(@"%s",__FUNCTION__);
//}
- (void)setNeedsDisplay
{
NSLog(@"%s",__FUNCTION__);
[super setNeedsDisplay];
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
NSLog(@"%s",__FUNCTION__);
[super drawLayer:layer inContext:ctx];// 如果去掉此句就不会执行drawRect!!!!!!!
CGContextAddEllipseInRect(ctx, CGRectMake(10,10,20,20));
CGContextSetFillColorWithColor(ctx, [UIColor blueColor].CGColor);
CGContextFillPath(ctx);
}
@end