1.什么是UIEvent
UIEvent代表iOS系統(tǒng)中的一個事件,可以分為三類:UIEventTypeTouches觸摸事件、UIEventTypeMotion運動事件、UIEventTypeRemoteControl遠程事件。
UIEventTypeTouches觸摸事件,通過點擊,拖拽,縮放等等觸發(fā)。
UIEventTypeMotion運動事件,通過搖晃屏幕等觸發(fā)。
UIEventTypeRemoteControl通過遠程事件控制,或者耳機等觸發(fā)。
UIEvent繼承于NSObject.
2.什么是UIResponder
在iOS當中,只有繼承自UIResponder的類才能處理各種事件。
我們常用的UIView、UIViewController、UIApplication都繼承自UIResponder,它們都能接收并處理事件。
@interface UIView : UIResponder<NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusEnvironment>
UIResponder中提供了處理上述三種UIEvent的方法,根據(jù)事件的類型有不同的處理方法。
3.什么是UITouch
當用戶的一根手指觸摸屏幕的時候會創(chuàng)建一個對應(yīng)的UITouch,這個UITouch會記錄手指運動的信息,比如說位置,時間,階段等等。手指在屏幕的時候系統(tǒng)會更新同一個UITouch對象,如果手指離開了屏幕,這個UITouch對象就被銷毀了。
我們可以發(fā)現(xiàn)處理點擊事件的方法里有兩個參數(shù)。
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
??:一次完整的觸摸事件只會產(chǎn)生一個UIEvent對象,也就是說不管手指在屏幕上怎么移動都是一個UIEvent對象。
而touches這個NSSet里面,裝著的是UITouch對象,從這個里面可以看出是單點觸摸還是多點觸摸。也就是說兩個手指同時觸摸屏幕,那么touches里就有兩個UITouch對象。
4.Gesture Recognizer
??:如果有事件到來時,視圖有附加的手勢識別器,則手勢識別器優(yōu)先處理事件。如果手勢識別器沒有處理事件,則將事件交給視圖處理,視圖如果未處理則順著響應(yīng)者鏈繼續(xù)向后傳遞。
也就是說手勢識別器的優(yōu)先級高于事件處理。如果手勢在事件響應(yīng)鏈中,那么手勢會把這個響應(yīng)鏈打斷。
????:比如說現(xiàn)在有兩個view,viewb在viewa的上面,兩個view都添加了手勢,那么我們點擊viewa的時候可以響應(yīng),但是點擊viewb的時候就沒有響應(yīng)了,這就是因為viewa上添加了手勢打斷了響應(yīng)鏈,所以viewb響應(yīng)不到這個點擊事件了。
5.UIControl
UIControl對于事件的處理會打破上面的規(guī)則。
????:比如在viewa上添加了一個button,給這個button和這個views都添加了手勢,那么views和button的手勢都可以響應(yīng)。因為UIButton繼承于UIControl,也就是說如果UIButton是第一響應(yīng)者,他的事件是由UIApplication直接派發(fā)的,不通過響應(yīng)鏈傳遞,如果不能處理再交給響應(yīng)鏈。
而如果是剛才那種情況,給UIButton addTarget的話,這個target是不會被響應(yīng)的。
所以說這個action會因為父類的響應(yīng)鏈被打斷而無法執(zhí)行,而gesture不會因為父類的響應(yīng)鏈被打斷而無法執(zhí)行。
6.事件響應(yīng)邏輯
當事件到來時,會通過hitTest和pointInside兩個方法,從Window開始向上面的視圖查找,找到第一響應(yīng)者的視圖。找到第一響應(yīng)者后,系統(tǒng)會判斷其是繼承自UIControl還是UIResponder,如果是繼承自UIControl,則直接通過UIApplication直接向其派發(fā)消息,并且不再向響應(yīng)者鏈派發(fā)消息。
如果是繼承自UIResponder的類,則調(diào)用第一響應(yīng)者的touchesBegin,并且不會立即執(zhí)行touchesEnded,而是調(diào)用之后順著響應(yīng)者鏈向后查找。如果在查找過程中,發(fā)現(xiàn)響應(yīng)者鏈中有的視圖添加了手勢,則進入手勢的代理方法中,如果代理方法返回可以響應(yīng)這個事件,則將第一響應(yīng)者的事件取消,并調(diào)用其touchesCanceled方法,然后由手勢來響應(yīng)事件。
如果手勢不能處理事件,則交給第一響應(yīng)者來處理。如果第一響應(yīng)者也不能響應(yīng)事件,則順著響應(yīng)者鏈繼續(xù)向后查找,直到找到能夠處理事件的UIResponder對象。如果找到UIApplication還沒有對象響應(yīng)事件的話,則將這次事件丟棄。