YYKit--YYLabel源碼分析

一、YYLabel實現的總體思路

其實YYLabel主要就是為了實現異步繪圖,提高性能,為此做了好多東西。

1、使用自定義的Layer,YYAsyncLayer

2、在YYAsyncLayer中實現異步繪圖,因為系統默認的繪圖都是在主線程執行了的,這里要實現異步繪圖,那么就得擯棄掉系統的繪圖方法,自己去實現。所以這里得花費很多功夫。所以說,提高性能是要付出很多的。

二、下面開始進入代碼分析:

(1)使用自定義的Layer,YYAsyncLayer

在YYLabel中重寫了下面的方法:

+ (Class)layerClass {

???return [YYAsyncLayer class];

}

就是修改了View的主Layer層,把YYAsyncLayer的實例作為主Layer層

(2)View與Layer的關系

View其實就是Layer的代理,Layer是View的底層實現,View是Layer的管理類。繪圖和坐標等操作都是在Layer中實現的,View只是訪問Layer中的相關方法。

(3)系統View的繪圖過程:

1、調用setNeedsDisplay

2、調用Layer中的display方法

3、在display中會調用Layer的drawInContext方法

4、在drawInContext中會調用代理方法drawLayer:(CALayer *)layer

inContext:(CGContextRef)ctx,這就進入到View了

5、最后View在代理實現中調用了drawRect方法,這方法就是我們經常用到了那個。

我寫了demo驗證了上面的過程,結果如下:

(4) YYLabe的繪圖過程

在YYAsyncLayer中,我們找到display方法:

- (void)display {

???super.contents = super.contents;

???[self _displayAsync:_displaysAsynchronously];

}

重寫了display方法,但沒有調用super方法,就是說上面的流程已經被打斷了,那么view的系統繪圖方法都不會被調用。

通過代理方法newAsyncDisplayTask得到了YYAsyncLayerDisplayTask類實例,再通過調用類實例的block方法直接返回到View中進行操作。作者打斷了之前的繪圖流程,但這里是通過block進入到UIView中進行繪圖操作,這樣就可以完全控制繪圖過程。

在_displayAsync方法中:

可見,這里是在線程中操作的,先創建了上下文context,然后再調用代理方法:task.display(context, size,isCancelled),所以UIView在代理實現中的繪圖操作都是在線程中執行的,這里就實現了異步繪圖。

(5) newAsyncDisplayTask的代理實現

上面是得到一些繪圖需要的參數,其中最主要的是YYTextLayout對象,里面包含了很多繪圖需要的信息。

然后是block display方法:

上面提到這個block實在非主線程執行的,這里執行了真正的繪圖操作,繪圖操作方法:

[drawLayoutdrawInContext:context size:size point:point view:nil layer:nil debug:debug cancel:isCancelled];中。

具體的繪圖還是挺復雜了,看起來有點吃力,以后有機會再研究下。好了,整個YYLabel的實現流程已經分析完成,是不是覺得源碼作者很牛逼。作者為了實現異步繪圖,花了好多的功夫。

總結:

所以整體的流程是:首先得理解CALayer與UIView的關系,UIView就是CALayer的代理,CALayer實現真正的繪制工作,繪制好之后,再通過代理傳遞到UIView的drawRect方法,給UIView進一步繪制的工作,不過UIView也基本不需要在drawRect做什么東西。

YYkit利用這個原理。自定義了自己的YYLayer和YYLabel,通過在YYLabel上的layerClass關聯YYLayer。因為不能使用CALayer的繪制代碼(UIKit那套是不能在子線程執行),所有必須打斷掉以前CALayer的執行順序(不讓它使用之前的繪制)。YYKit在YYLayer上重寫了display方法,打斷了以前的順序,讓它不去執行之前的繪制。接著在display方法里,通過代理從YYLabel得到一個task,YYLabel實現task.display()。YYLayer創建一個上下文畫板,然后通過在子線程調用task.display(context)傳遞畫板-context給YYLabel,YYLabel在畫板上用coreGraphic繪制正在的內容。繪制好后,在YYLayer上通過主線程返回給layer的self.contents,畫面就展示出來了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。