UILabel的DrawDrect方法

一、问题

  如果继承UILabel实现自己的一个Label,并且在子类的DrawRect方法中留空,什么都不写,会发生什么?

  代码如下:

  VC

@interface ViewController ()

@property (nonatomic, strong) DrawTestLabel *dwLabel;

@end

@implementation ViewController

- (DrawTestLabel *)dwLabel
{
    if(!_dwLabel) {
        _dwLabel = [[DrawTestLabel alloc] init];
        _dwLabel.textAlignment = NSTextAlignmentCenter;
    }
    
    return _dwLabel;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [[self view] setBackgroundColor:[UIColor greenColor]];
    [[self dwLabel] setFrame:CGRectMake(0, 0, 200, 50)];
    [[self view] addSubview:[self dwLabel]];
    [[self dwLabel] setText:@"Hello"];
    [[self dwLabel] setCenter:[self view].center];
}


@end

  Label

@implementation DrawTestLabel


- (void)drawRect:(CGRect)rect {
    // Drawing code
//    [super drawRect:rect];
}


@end

  注释调调用父类的DrawRect方法之后,会发现屏幕上面什么都没有

  打开Xcode调试之后,会发现存在一个透明的图层

  UILabel的DrawDrect方法

 

二、问题分析

  我们知道,UIView和Layer的关系,Layer负责画面渲染,UIVIew负责事件响应;

  在CALayer中通过实现 CALayerDelegate来实现画面的绘制,通常一个layer的delegate是UIView自身。

  CALayerDelegate 的方法 drawlayer:incontext方法在每次绘制的时候,会调用UIView的Drawrect方法,在UIView实现了DrawRect的方法下。

  UILabel的DrawDrect方法

  

  那么上面自己继承的UILbel,重写Drawrect方法之后,大致的逻辑如下

  1、CALayer接受到系统的回调,开始渲染

  2、系统发现layer(Label)实现了Drawrect方法,那么会创建一个透明的画布,大小是UILabel的发小,scale是屏幕的scale

  3、通过delegate调用Drawrect方法,在这个画布之上绘制内容

  4、新的UILabel通过TextKit(底层是CoreText)来绘制文字到这个画布之上,这一段是在CPU上完成的

  5、绘制完成的bitmap ,再一次Runloop循环中,会通过系统统一提交给后台的renderserver

  6、render server进程处理不同的图层,通过操作GPU进行叠加渲染操作

  

  为什么Drawrect消耗比较高?

  因为绘制在CPU上面操作

  绘制完成的bitmap,会通过跨进城IPC传递给render server存在系统调用消耗

  render 传递内存中的bitmap到GPU的缓存上面生成纹理 ,再次产生消耗

 

  普通的UIView通过设置属性的方式,不涉及到传递大块内存的操作,这些类似背景色、透明度、都是通过renderserver来完成的,GPU操作效率会比较高。

  

  

上一篇:手把手教你iOS控件之UILabel


下一篇:如何改掉喜欢删代码注释的习惯?