事件傳遞和響應者鏈條
iOS中的事件
首先iOS中的事件分為三種:
- 觸控事件
- 加速計事件
- 遠端控制事件
那麼這篇文章主要講解就是觸控事件!
事件的產生和傳遞
傳遞過程如下:
發生觸控事件後,系統會將該時間加入到一個由UIApplication管理的事件佇列中
UIApplication會從事件佇列中取出最前面的事件,然後將事件分發下去以便處理,通常,先發送事件給應用程式的主視窗(keywindow)
主視窗會在檢視層次結構中找到一個最適合處理事件的檢視來處理
找到合適的檢視控制元件後,就會呼叫檢視控制元件的touchs方法來做具體的事件處理
- touchesBegan…
- touchesMoved…
- touchesEnded..
舉例說明:
在上圖中,如果我們點選了綠色View,那麼事件的傳遞就是:
UIApplication -> UIWindow -> 白色View -> 綠色View
所以這就引出一個結論:如果父控制元件不能接受觸控事件,那麼子控制元件就不可能接受到觸控事件
如何找到最適合的控制元件來處理事件呢?
這個解決方案是遵循一套原則的:
- 自己是否能接受到觸控事件?
- 觸控點是否在自己身上?
- 從後往前遍歷子控制元件,重複上面兩個步驟(遞迴)
- 如果沒有適合的子控制元件,那麼就自己最適合處理
該原則就是hitTest方法的底層實現原理,同時 hitTest內部也是通過呼叫pointInside方法去判斷觸控點在不在自己身上
舉例說明:
按照上圖所示,假如檢視新增順序是: 白色View中先新增綠色View,再橙色View,橙色View中先新增藍色View, 再紅色View,藍色View中有黃色View
事件處理詳細流程:這時我們點選了橙色View,那麼首先UIWindow會接受事件(上面兩條滿足), 然後找到子控制元件白色View(也滿足), 接著找到子控制元件橙色View(該View是後新增的,也滿足),所以找到子控制元件紅色View(後新增的,觸控點不在自己身上,不滿足),接著找到子控制元件藍色View(觸控點不在自己身上,不滿足),由於橙色View的子控制元件都不滿足以上條件,所以就自己處理該事件
檢視不接受觸控事件的三種情況
userInteractionEnabled = NO, 不接受使用者互動
hidden = YES, 隱藏
alpha = 0.0~0.01, 透明
提示:UIImageView預設userInteractionEnabled就為NO,所以UIImageView以及它的子控制元件預設是不能接受觸控事件的
觸控事件處理的詳細過程
使用者點選屏幕後產生一個觸控事件,經過一系列的傳遞後,會找到最合適的檢視控制元件來處理該觸控事件
找到最合適的檢視控制元件來處理該觸控事件後,就會呼叫檢視控制元件的touches方法來做具體的事件處理
這些touches方法預設做法是將事件按照響應者鏈條向上傳遞,將事件交給上一個響應者物件處理(也就是判斷當前響應者是否實現touches方法,沒有實現預設會把事件傳遞給上一個響應者)
那麼又引申出另外一個概念:何為響應者, 何為響應者鏈條?
響應者物件,響應者鏈條
在iOS中不是任何物件都可以處理事件,只有繼承自UIResponder的物件才能接受並處理事件,我們稱之為“響應者物件”
響應者鏈條如下圖所示:
很多響應者連結在一起組合起來的一個鏈條稱為響應者鏈條!
那麼如何判斷當前響應者的上一個響應者物件是誰呢?
判斷當前的view是不是控制器的view,如果是控制器的view,那麼上一個響應者就是控制器
如果當前的view不是控制器的view,那上一個響應者就是父控制元件
在檢視層次結構中的最頂級檢視,如果也不能處理接受到的事件或訊息,那麼就會將事件或訊息傳遞給window物件處理,如果window物件也不能處理,則將事件或訊息傳遞給UIApplication物件,如果UIApplication物件也不能處理該事件或訊息,則將其丟棄!
響應者鏈條有何作用呢?
可以讓一個觸控事件發生的時候讓多個響應者同時響應!