view和layer關(guān)系

前言

前面發(fā)了一篇iOS 面試的文章,在說到 UIView 和 CALayer 的區(qū)別和聯(lián)系的時(shí)候,被喵神指出沒有切中要點(diǎn),所以這里就 CALayer 和 UIView 這個(gè)問題重新整理了下。這里會(huì)先分條解釋,最后會(huì)在文章的結(jié)尾給出概括性總結(jié)。

1.首先UIView可以響應(yīng)事件,Layer不可以.

UIKit使用UIResponder作為響應(yīng)對(duì)象,來響應(yīng)系統(tǒng)傳遞過來的事件并進(jìn)行處理。UIApplication、UIViewController、UIView、和所有從UIView派生出來的UIKit類(包括UIWindow)都直接或間接地繼承自UIResponder類。

在 UIResponder中定義了處理各種事件和事件傳遞的接口, 而 CALayer直接繼承 NSObject,并沒有相應(yīng)的處理事件的接口。

下面列舉一些處理觸摸事件的接口

– touchesBegan:withEvent:

– touchesMoved:withEvent:

– touchesEnded:withEvent:

– touchesCancelled:withEvent:

2.View和CALayer的Frame映射及View如何創(chuàng)建CALayer.

一個(gè) Layer 的 frame 是由它的 anchorPoint,position,bounds,和 transform 共同決定的,而一個(gè) View 的 frame 只是簡(jiǎn)單的返回 Layer的 frame,同樣 View 的 center和 bounds 也是返回 Layer 的一些屬性。(PS:center有些特列)為了證明這些,我做了如下的測(cè)試。

首先我自定義了兩個(gè)類CustomView,CustomLayer分別繼承 UIView 和 CALayer

在 CustomView 中重寫了

+ (Class)layerClass {

return[CustomLayer class];

}

- (void)setFrame:(CGRect)frame {? ?

?[supersetFrame:frame];

}

- (void)setCenter:(CGPoint)center {? ??

[supersetCenter:center];

}

- (void)setBounds:(CGRect)bounds { ? ?

? ? ? [supersetBounds:bounds];

? }

同樣在 CustomLayer中同樣重寫這些方法。只是setCenter方法改成setPosition方法

3.UIView主要是對(duì)顯示內(nèi)容的管理而 CALayer 主要側(cè)重顯示內(nèi)容的繪制。

首先我們會(huì)發(fā)現(xiàn),我們?cè)?[view initWithFrame] 的時(shí)候調(diào)用私有方法【UIView _createLayerWithFrame】去創(chuàng)建 CALayer。

然后我在創(chuàng)建 View 的時(shí)候,在 Layer 和 View 中Frame 相關(guān)的所有方法中都加上斷點(diǎn),可以看到大致如下的調(diào)用順序如下

[UIView _createLayerWithFrame]

[Layer setBounds:bounds]

[UIView setFrame:Frame]

[Layer setFrame:frame]

[Layer setPosition:position]

[Layer setBounds:bounds]

我發(fā)現(xiàn)在創(chuàng)建的過程只有調(diào)用了 Layer 的設(shè)置尺寸和位置的然而并沒有調(diào)用View 的SetCenter和SetBounds方法。

然后我發(fā)現(xiàn)當(dāng)我修改了 view的bounds.size或者bounds.origin的時(shí)候也只會(huì)調(diào)用上邊 Layer的一些方法。所以我大膽的猜一下,View 的 Center 和 Bounds 只是直接返回layer 對(duì)應(yīng)的 Position 和 Bounds.

View中frame getter方法,bounds和center,UIView并沒有做什么工作;它只是簡(jiǎn)單的各自調(diào)用它底層的CALayer的frame,bounds和position方法。

關(guān)于 Frame 的理解參考:http://www.cocoachina.com/industry/20131209/7498.html


3.我在 UIView 和 CALayer 分別重寫了父類的方法。

[UIView drawRect:rect]//UIView

[CALayer display]//CALayer

可以看到 UIView 是 CALayer 的CALayerDelegate,我猜測(cè)是在代理方法內(nèi)部[UIView(CALayerDelegate) drawLayer:inContext]調(diào)用 UIView 的 DrawRect方法,從而繪制出了 UIView 的內(nèi)容.


4.在做 iOS 動(dòng)畫的時(shí)候,修改非 RootLayer的屬性(譬如位置、背景色等)會(huì)默認(rèn)產(chǎn)生隱式動(dòng)畫,而修改UIView則不會(huì)。

對(duì)于每一個(gè) UIView 都有一個(gè) layer,把這個(gè) layer 且稱作RootLayer,而不是 View 的根 Layer的叫做 非 RootLayer。我們對(duì)UIView的屬性修改時(shí)時(shí)不會(huì)產(chǎn)生默認(rèn)動(dòng)畫,而對(duì)單獨(dú) layer屬性直接修改會(huì),這個(gè)默認(rèn)動(dòng)畫的時(shí)間缺省值是0.25s.

在 Core Animation 編程指南的 “How to Animate Layer-Backed Views” 中,對(duì)為什么會(huì)這樣做出了一個(gè)解釋:

UIView 默認(rèn)情況下禁止了 layer 動(dòng)畫,但是在 animation block 中又重新啟用了它們

是因?yàn)槿魏慰蓜?dòng)畫的 layer 屬性改變時(shí),layer 都會(huì)尋找并運(yùn)行合適的 'action' 來實(shí)行這個(gè)改變。在 Core Animation 的專業(yè)術(shù)語中就把這樣的動(dòng)畫統(tǒng)稱為動(dòng)作 (action,或者 CAAction)。

layer 通過向它的 delegate 發(fā)送 actionForLayer:forKey: 消息來詢問提供一個(gè)對(duì)應(yīng)屬性變化的 action。delegate 可以通過返回以下三者之一來進(jìn)行響應(yīng):

它可以返回一個(gè)動(dòng)作對(duì)象,這種情況下 layer 將使用這個(gè)動(dòng)作。

它可以返回一個(gè) nil, 這樣 layer 就會(huì)到其他地方繼續(xù)尋找。

它可以返回一個(gè) NSNull 對(duì)象,告訴 layer 這里不需要執(zhí)行一個(gè)動(dòng)作,搜索也會(huì)就此停止。

當(dāng) layer 在背后支持一個(gè) view 的時(shí)候,view 就是它的 delegate;

這部分的具體內(nèi)容參考:http://objccn.io/issue-12-4/


總結(jié)

總接來說就是如下幾點(diǎn):

每個(gè) UIView 內(nèi)部都有一個(gè) CALayer 在背后提供內(nèi)容的繪制和顯示,并且 UIView 的尺寸樣式都由內(nèi)部的 Layer 所提供。兩者都有樹狀層級(jí)結(jié)構(gòu),layer 內(nèi)部有 SubLayers,View 內(nèi)部有 SubViews.但是 Layer 比 View 多了個(gè)AnchorPoint

在 View顯示的時(shí)候,UIView 做為 Layer 的 CALayerDelegate,View 的顯示內(nèi)容由內(nèi)部的 CALayer 的 display

CALayer 是默認(rèn)修改屬性支持隱式動(dòng)畫的,在給 UIView 的 Layer 做動(dòng)畫的時(shí)候,View 作為 Layer 的代理,Layer? 通過 actionForLayer:forKey:向 View請(qǐng)求相應(yīng)的 action(動(dòng)畫行為)

layer 內(nèi)部維護(hù)著三分 layer tree,分別是 presentLayer Tree(動(dòng)畫樹),modeLayer Tree(模型樹), Render Tree (渲染樹),在做 iOS動(dòng)畫的時(shí)候,我們修改動(dòng)畫的屬性,在動(dòng)畫的其實(shí)是 Layer 的 presentLayer的屬性值,而最終展示在界面上的其實(shí)是提供 View的modelLayer

兩者最明顯的區(qū)別是 View可以接受并處理事件,而 Layer 不可以

參考鏈接

http://blog.csdn.net/weiwangchao_/article/details/7771538

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過程并不復(fù)雜,今天將帶大家一窺ios動(dòng)畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,686評(píng)論 6 30
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過程并不復(fù)雜,今天將帶大家一窺iOS動(dòng)畫全貌。在這里你可以看...
    F麥子閱讀 5,258評(píng)論 5 13
  • 轉(zhuǎn)載:http://www.itdecent.cn/p/32fcadd12108 每個(gè)UIView有一個(gè)伙伴稱為l...
    F麥子閱讀 6,567評(píng)論 0 13
  • 前言 前面發(fā)了一篇iOS 面試的文章,在說到 UIView 和 CALayer 的區(qū)別和聯(lián)系的時(shí)候,被喵神指出沒有...
    Mz楓閱讀 857評(píng)論 0 4
  • Core Animation其實(shí)是一個(gè)令人誤解的命名。你可能認(rèn)為它只是用來做動(dòng)畫的,但實(shí)際上它是從一個(gè)叫做Laye...
    小貓仔閱讀 3,950評(píng)論 1 4

友情鏈接更多精彩內(nèi)容