1. 程式人生 > >事件傳遞和響應者鏈條

事件傳遞和響應者鏈條

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物件也不能處理該事件或訊息,則將其丟棄!

響應者鏈條有何作用呢?

可以讓一個觸控事件發生的時候讓多個響應者同時響應!