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調試之後,會發現存在一個透明的圖層

  

 

二、問題分析

  我們知道,UIView和Layer的關係,Layer負責畫面渲染,UIVIew負責事件響應;

  在CALayer中通過實現 CALayerDelegate來實現畫面的繪製,通常一個layer的delegate是UIView自身。

  CALayerDelegate 的方法 drawlayer:incontext方法在每次繪製的時候,會調用UIView的Drawrect方法,在UIView實現了DrawRect的方法下。

  

  

  那麼上面自己繼承的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操作效率會比較高。

  

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章