A.事件的產(chǎn)生和傳遞
發(fā)生觸摸事件后,系統(tǒng)會將該事件加入到一個由UI
application管理的事件隊列中
UIApplication會從事件隊列中取出最前面的事件,并將事件分發(fā)下去以便處理,通常,先發(fā)送事件給應(yīng)用程序的主窗口(keyWindow)
主窗口會在視圖層次結(jié)構(gòu)中找到一個最合適的視圖來處理觸摸事件,這也是整個事件處理過程的第一步
找到合適的視圖控件后,就會調(diào)用視圖控件的touches方法來作具體的事件處理
touchesBegan…
touchesMoved…
touchedEnded…
B.不接受事件傳遞的情況
不接收用戶交互
userInteractionEnabled = NO
隱藏
hidden = YES
透明
alpha = 0.0 ~ 0.01
提示:UIImageView的userInteractionEnabled默認(rèn)就是NO,因此UIImageView以及它的子控件默認(rèn)是不能接收觸摸事件的
C.觸摸事件處理的過程
用戶點擊屏幕后產(chǎn)生的一個觸摸事件,經(jīng)過一些列的傳遞過程后,會找到最合適的視圖控件來處理這個事件
找到最合適的視圖控件后,就會調(diào)用控件的touches方法來作具體的事件處理
touchesBegan…
touchesMoved…
touchedEnded…
這些touches方法的默認(rèn)做法是將事件順著響應(yīng)者鏈條向上傳遞,將事件交給上一個響應(yīng)者進行處理
D.響應(yīng)者鏈條

For the app on the left, the event follows this path:
-
The initial view attempts to handle the event or message. If it can’t handle the event, it passes the event to itssuperview, because the initial view is not the top most view in its view controller’s view hierarchy.
-
The superview attempts to handle the event. If the superview can’t handle the event, it passes the event to its superview, because it is still not the top most view in the view hierarchy.
-
The topmost view in the view controller’s view hierarchy attempts to handle the event. If the topmost view can’t handle the event, it passes the event to its view controller.
-
The view controller attempts to handle the event, and if it can’t, passes the event to the window.
-
If the window object can’t handle the event, it passes the event to the singleton app object.
-
If the app object can’t handle the event, it discards the event.
The app on the right follows a slightly different path, but all event delivery paths follow these heuristics:
-
A view passes an event up its view controller’s view hierarchy until it reaches the topmost view.
-
The topmost view passes the event to its view controller.
-
The view controller passes the event to its topmost view’s superview.
Steps 1-3 repeat until the event reaches the root view controller.
-
The root view controller passes the event to the window object.
-
The window passes the event to the app object.
對于左邊的app來說,事件軌跡是這樣的:(單控制器)
1.初始控件嘗試處理事件或者信息,如果它不能處理,因為初始控件不是它所在控件控制器的控件層的最頂層控件,所以傳遞到它的父控件。
2.“父控件”也嘗試跟進處理事件,如果這個“父控件”還是不能處理,由于此"父控件"還不是控制器控件層的最頂層控件,所以還會傳遞這個事件給它的父控件(嗯,初始控件的“爺控件”)。
3.控制器空間層的最頂層控件拿到事件,努力想進行處理,如果它還是沒有這個能力,就會傳遞到它所屬的控制器。
4.控制器還不行,只能傳遞給窗口(window)了
5.window不能處理的話,還會繼續(xù)傳遞給app單例對象(Application)
6.如果最后app都不能處理,只能放棄這個事件了。
對于右邊的app來講,事件軌跡稍稍不同,不過也都遵循下列規(guī)則:(多控制器)
1.一個控件按照它的控制器控件層次往上傳遞事件,在此控制器控件層中傳遞匹配有處理能力的控件,直到到達(dá)最頂層控件。
2.上述控件層的最頂層控件不能處理,把事件傳遞給控制器。
3.如果“2”的控制器不能處理,把事件傳遞給它的父控件,重復(fù)1-3,直到處理了事件,或者到達(dá)根控制器。
4.如果根控制器不能處理,傳遞事件給window對象
5.如果window對象也不能處理,傳遞事件給app對象(application)
6.app最后也不能處理,舍棄事件
D.監(jiān)聽觸摸事件
如果想監(jiān)聽一個view上面的觸摸事件,之前的做法是
自定義一個view
實現(xiàn)view的touches方法,在方法內(nèi)部實現(xiàn)具體處理代碼
通過touches方法監(jiān)聽view觸摸事件,有很明顯的幾個缺點
必須得自定義view
由于是在view內(nèi)部的touches方法中監(jiān)聽觸摸事件,因此默認(rèn)情況下,無法讓其他外界對象監(jiān)聽view的觸摸事件
不容易區(qū)分用戶的具體手勢行為
iOS 3.2之后,蘋果推出了手勢識別功能(Gesture Recognizer),在觸摸事件處理方面,大大簡化了開發(fā)者的開發(fā)難度
多種手勢識別器: