UIView:UIView->UIResponder->NSObject
UIViewController:UIViewController->UIResponder->NSObject
UIWindow:UIWindow->UIView
UIButton/UISwitch/UITextField:UIButton/UISwitch/UITextField->UIControl->UIView
UILabel:UILabel->UIView
CALayer:CALayer->NSObject
UIWindow算是一種特殊的View敞贡,他默認(rèn)在視圖最頂端悼粮,有自己的一套優(yōu)先級(jí)惕它。可以創(chuàng)建多個(gè)因块,控制顯示級(jí)別。
CALayer和UIView是相互依賴的籍铁,繼承于UIView的都有l(wèi)ayer這個(gè)屬性涡上,CALayer用于渲染視圖,繪制具體的像素拒名。UIView只是提供一個(gè)容器吩愧。真正繪制內(nèi)容的是CALayer。UIView的主layer以外增显,對(duì)它的subLayer雁佳,也就是子layer的屬性進(jìn)行更改,系統(tǒng)將自動(dòng)進(jìn)行動(dòng)畫生成同云。
從上面的繼承關(guān)系可以看出糖权,繼承于UIResponder的才有用戶點(diǎn)擊事件。
UIControl是控件類的基類梢杭,它是一個(gè)抽象基類温兼,我們不能直接使用UIControl類來實(shí)例化控件,它只是為控件子類定義一些通用的接口武契,并提供一些基礎(chǔ)實(shí)現(xiàn)募判,以在事件發(fā)生時(shí),預(yù)處理這些消息并將它們發(fā)送到指定目標(biāo)對(duì)象上咒唆。他是將UIResponder中的復(fù)雜觸摸事件封裝成了簡(jiǎn)單事件届垫。
NSObject是所有控件的基類。
UIView內(nèi)部分三個(gè)樹:
第一份全释,邏輯樹装处,就是代碼里可以操縱的,例如更改layer的屬性等等就在這一份。
第二份妄迁,動(dòng)畫樹寝蹈,這是一個(gè)中間層,系統(tǒng)正在這一層上更改屬性登淘,進(jìn)行各種渲染操作箫老。
第三份,顯示樹黔州,這棵樹的內(nèi)容是當(dāng)前正被顯示在屏幕上的內(nèi)容耍鬓。
這三棵樹的邏輯結(jié)構(gòu)都是一樣的,區(qū)別只有各自的屬性流妻。
說一下事件響應(yīng)鏈牲蜀。
具體的事件響應(yīng)方式就不介紹了,幾種手勢(shì)那種绅这。
用戶點(diǎn)擊屏幕以后我們可以通過hitTest:withEvent:來獲取點(diǎn)擊的點(diǎn)和view涣达。
在iOS中不是任何對(duì)象都能處理事件,只有繼承了UIResponder的對(duì)象才能接受并處理事件证薇,我們稱之為“響應(yīng)者對(duì)象”峭判。這個(gè)上面已經(jīng)講過了。
假設(shè)現(xiàn)在有個(gè)頁(yè)面棕叫,VC->View(兩個(gè)子視圖-BView,DView)->BView(子視圖CView)
這時(shí)候用戶點(diǎn)擊了CView林螃,響應(yīng)鏈:
用戶觸摸->產(chǎn)生觸摸事件->UIApplication事件隊(duì)列->UIWindow->UIView->AView->DView->BView->CView
也就是說,當(dāng)用戶產(chǎn)生觸摸事件以后俺泣,系統(tǒng)會(huì)先去查找application疗认,然后交給window,如果接收不了會(huì)繼續(xù)遍歷VC中的View伏钠,這個(gè)時(shí)候是優(yōu)先subView中的最后一個(gè)横漏,也就是視圖最頂端,如果找不到繼續(xù)遍歷View的子視圖熟掂,同樣的方式缎浇,優(yōu)先遍歷subView中最后一個(gè)。直到找到響應(yīng)者赴肚。
注意:
這里有這樣一個(gè)方法素跺,- (nullable UIResponder *)nextResponder,獲取當(dāng)前view的下一個(gè)響應(yīng)者誉券,但是有前輩已經(jīng)發(fā)現(xiàn)這個(gè)方法查找出來的響應(yīng)鏈?zhǔn)清e(cuò)誤的指厌,因?yàn)樗檎业降氖撬衦esponse,包括VC踊跟。但是很明顯VC并不應(yīng)該是用戶事件的響應(yīng)者踩验。如果通過這個(gè)方法來查找下一個(gè)響應(yīng)視圖得到的結(jié)果是錯(cuò)誤的。
然后查閱View里面的方法,大概猜到這才應(yīng)該是獲取到當(dāng)前響應(yīng)事件的下一個(gè)響應(yīng)者View箕憾。
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;
-?(BOOL)pointInside:(CGPoint)point?withEvent:(nullable?UIEvent?*)event;
然后通過runtime替換著兩個(gè)方法牡借,果然獲取到的響應(yīng)鏈變了,具體的就是上面的圖片所示袭异。