鏈接:http://www.lxweimin.com/p/cb0314b72883
回到我們上面問過的問題,BView只有touchBegan, touchesCancelle 的原因是什么?答案在于整個觸摸事件全過程
1.系統會通過hitTest的方法尋找響應鏈,完成之后會形成下圖模型。
event handing squence.png
圖中最右邊是響應鏈,中間是關聯在相應鏈在視圖上的手勢
2.有了模型之后就會發生圖上的三個步驟
第一步:系統會將所有的 Touch message 優先發送給 關聯在響應鏈上的全部手勢。手勢根據Touch序列消息和手勢基本規則更改自己的狀態(有的可能失敗,有的可能識別等等)。如果沒有一個手勢對Touch message 進行攔截(攔截:系統不會將Touch message 發送給響應鏈頂部響應者),系統會進入第二步
第二步:系統將Touch message 發送給響應鏈 頂部的 視圖控件,頂部視圖控件這個時候就會調用Touch相關的四個方法中的某一個。之后進入自定義Touch message轉發
第三步:自定義Touch message轉發可以繼承UIResponser的四個Touch函數做轉發。
解釋一下第一步中說的攔截,手勢會表明是否攔截該Touch Message,主要由下面三個屬性控制。
再回到那道題目,如果我們想hitTestView的toucheEnd函數依然能得到調用,怎么辦?其實UIGestureRecognizer有三個屬性
@property(nonatomic) BOOL cancelsTouchesInView;? ? ? //defaultisYES. causes touchesCancelled:withEvent:orpressesCancelled:withEvent:tobe senttothe viewforalltouchesorpresses recognized as partofthis gesture immediately before the action methodiscalled.@property(nonatomic) BOOL delaysTouchesBegan;? ? ? ? //defaultisNO.? causesalltouchorpress eventstobe deliveredtothe target view onlyafterthis gesture has failed recognition. settoYEStoprevent views from processing any touchesorpresses that may be recognized as partofthis gesture@property(nonatomic) BOOL delaysTouchesEnded;? ? ? ? //defaultisYES. causes touchesEndedorpressesEnded eventstobe deliveredtothe target view onlyafterthis gesture has failed recognition. this ensures that a touchorpress thatispartofthe gesture can be cancelledifthe gestureisrecognized
cancelsTouchesInView
默認為YES,表明當手勢識別了該事件,系統會將Touch cancel消息發送給hitTestView ,并調用hitTestView的TouchCancel。設置為NO,不會再收到TouchCancel
delaysTouchesBegan
默認為YES, 表明無論什么情況下,不會攔截Touch began消息。如果設置為NO,只要有一個手勢不識別失敗,都不會發送Touch began到響應鏈的第一響應者。
delaysTouchesEnded
默認為NO, 和delaysTouchesBegan類似,不過它是用來控制TouchEnd message的攔截
總結
iOS整個事件處理的過程就是這樣,系統為完成整個交互做了很多東西,核心點如下:
事件分發過程分為:1.尋找響應鏈;2.事件消息分發
響應網是事件響應的基礎,響應鏈是事件響應的具體路徑。
事件消息分發優先發送給手勢集合,手勢內部會做沖突處理,過濾消息。不被過濾的消息會傳遞給響應鏈對象。