圖層繪制
繪制主要是CPU繪制湖员,運(yùn)用Core Graphic技術(shù),可以支持異步繪制(CoreGraphic已經(jīng)支持線程安全)娘摔。UIView只是對(duì)CALayer的淺封裝窄坦,CALayer負(fù)責(zé)繪制和顯示,因此繪制的輸出就是CALayer的contents屬性凳寺。繪制的結(jié)果是一張bitmap鸭津,可以直接轉(zhuǎn)換為紋理提交給GPU渲染。
繪制時(shí)機(jī)
當(dāng)在操作 UI 時(shí)肠缨,比如改變了 Frame逆趋、更新了 UIView/CALayer 的層次時(shí),或者手動(dòng)調(diào)用了 UIView/CALayer 的 setNeedsLayout/setNeedsDisplay方法后晒奕,這個(gè) UIView/CALayer 就被標(biāo)記為待處理闻书,并被提交到一個(gè)全局的容器去。
蘋果注冊(cè)了一個(gè) Observer 監(jiān)聽(tīng) BeforeWaiting(即將進(jìn)入休眠) 和 Exit (即將退出Loop) 事件脑慧,回調(diào)去執(zhí)行一個(gè)很長(zhǎng)的函數(shù):
_ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv()个少。這個(gè)函數(shù)里會(huì)遍歷所有待處理的 UIView/CAlayer 以執(zhí)行實(shí)際的繪制和調(diào)整渗蟹,并更新 UI 界面。
這個(gè)函數(shù)內(nèi)部的調(diào)用棧大概是這樣的:
繪制細(xì)節(jié)
CALayer提供了三種繪制內(nèi)容的方式,若采用優(yōu)先級(jí)高的方式繪制了內(nèi)容抹镊,則低優(yōu)先級(jí)的則不會(huì)執(zhí)行宋光。
每一個(gè)UIView都有一個(gè)layer馏锡,每一個(gè)layer都有個(gè)content握童,這個(gè)content指向的是一塊緩存,叫做backing store也物。默認(rèn)情況下藕各,CALayer的content為空。若UIView的子類重寫了drawRect焦除,則UIView執(zhí)行完drawRect后激况,系統(tǒng)會(huì)為器layer的content開(kāi)辟一塊緩存,緩存大小為size = width*height*scale
,用來(lái)存放drawRect繪制的內(nèi)容乌逐。
即使重寫的drawRect啥也沒(méi)做竭讳,也會(huì)開(kāi)辟緩存,消耗內(nèi)存浙踢,所以盡量不要隨便重寫drawRect卻啥也不做绢慢。舉例說(shuō)明:
-(void)drawRect:(CGRect)rect{
NSLog(@"MyView.before.drawRect.layer.contents %@",self.layer.contents);
// CGContextRef context = UIGraphicsGetCurrentContext();
// draw something
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"MyView.after.drawRect.layer.contents %@",self.layer.contents);
});
}
MyView* myView = [[MyView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
[self.view addSubview:myView];
最后的輸出結(jié)果(模擬器是7 plus,屏幕scale為3):
MyView.before.drawRect.layer.contents (null)
MyView.after.drawRect.layer.contents <CABackingStore 0x7fa1a7715fe0 (buffer [600 600] BGRX8888)>
當(dāng)UIView被繪制時(shí)(從 CA::Transaction::commit:以后),CPU執(zhí)行drawRect洛波,通過(guò)context將數(shù)據(jù)寫入backing store胰舆。當(dāng)backing store寫完后,通過(guò)render server交給GPU去渲染蹬挤,將backing store中的bitmap數(shù)據(jù)顯示在屏幕上 缚窿。
參考
OpenGL原理介紹
如何在iOS上創(chuàng)建矢量圖形
Core Animation編程指南
視圖渲染、CPU和GPU卡頓原因及其優(yōu)化方案
UIView 繪制渲染機(jī)制
Core Animation高級(jí)理論知識(shí)匯總