iOS-UIResponse之事件響應鏈及其事件傳遞


UIResponse之事件響應鏈及其事件傳遞

我們的App與用戶進行交互,基本上是依賴於各種各樣的事件。一個視圖是一個事件響應者,可以處理點擊等事件,而這些事件就是在UIResponder類中定義的。

在UIKit中,UIApplication、UIView、UIViewController這幾個類都是直接繼承自UIResponder類。另外SpriteKit中的SKNode也是繼承自UIResponder類。因此UIKit中的視圖、控件、視圖控制器,以及我們自定義的視圖及視圖控制器都有響應事件的能力。這些對象通常被稱為響應對象,或者是響應者(以下我們統一使用響應者)。

什么是響應鏈

大多數事件的分發都是依賴響應鏈的。響應鏈是由一系列鏈接在一起的響應者(UIResponse子類)組成的。一般情況下,一條響應鏈開始於第一響應者,結束於application對象。如果一個響應者不能處理事件,則會將事件沿着響應鏈傳到下一響應者。

創建響應鏈

我們都知道在一個App中,所有視圖是按一定的結構組織起來的,即樹狀層次結構。除了根視圖外,每個視圖都有一個父視圖;而每個視圖都可以有0個或多個子視圖。而在這個樹狀結構構建的同時,也構建了一條條的事件響應鏈。

也就是說,響應鏈是隨着我們界面的搭建,而創建的。當我們調用addSubView:等搭建界面的方法時,默認的我們也創建了一個響應鏈的連接。而且這個響應鏈也不是一個響應鏈,准確的來說,應該是一個響應樹。

例如,我們創建了一個視圖:

對應的系統將自動創建一個響應鏈樹:

獲取第一響應者

既然響應樹在搭建界面,組織app結構的時候形成了,那么針對於一個事件(UIEvent)的響應鏈是怎么形成的呢?

一般情況下,一條響應鏈開始於第一響應者,結束於application對象。因此我們只要確定第一響應者,就可以確定整條響應鏈了。

下面是獲取第一響應者的方法:

當用戶觸發某一事件(觸摸事件或運動事件)后,UIKit會創建一個事件對象(UIEvent),該對象包含一些處理事件所需要的信息。然后事件對象被放到一個事件隊列中。這些事件按照先進先出的順序來處理。當處理事件時,程序的UIApplication對象會從隊列頭部取出一個事件對象,將其分發出去。通常首先是將事件分發給程序的主window對象,對於觸摸事件來講,window對象會首先嘗試將事件分發給觸摸事件發生的那個視圖上。這一視圖通常被稱為hit-test視圖,而查找這一視圖的過程就叫做hit-testing。

系統使用hit-testing來找到觸摸下的視圖,它檢測一個觸摸事件是否發生在相應視圖對象的邊界之內(即視圖的frame屬性,這也是為什么子視圖如果在父視圖的frame之外時,是無法響應事件的)。如果在,則會遞歸檢測其所有的子視圖。包含觸摸點的視圖層次架構中最底層的視圖就是hit-test視圖。在檢測出hit-test視圖后,系統就將事件發送給這個視圖來進行處理。

以剛剛視圖為代表,講述講述hit-testing過程

假設用戶點擊了視圖E,系統按照以下順序來查找hit-test視圖:
  1. 點擊事件發生在視圖A的邊界內,所以檢測子視圖B和C;
  2. 點擊事件不在視圖B的邊界內,但在視圖C的邊界范圍內,所以檢測子圖片D和E;
  3. 點擊事件不在視圖D的邊界內,但在視圖E的邊界范圍內;

視圖E是包含觸摸點的視圖層次架構中最底層的視圖(倒樹結構),所以它就是hit-test視圖。

因此,我們就可以得到此點擊事件的響應鏈了

下面是hit-testing詳細介紹:

iOS事件分發機制(一) hit-Testing

iOS事件分發機制(二)The Responder Chain

通過事件響應鏈, 傳遞事件

剛剛獲取了事件響應鏈,現在我們可以把事件放在響應鏈上進行傳遞了。

最有機會處理事件的對象是hit-test視圖或第一響應者。如果這兩者都不能處理事件,UIKit就會將事件傳遞到響應鏈中的下一個響應者。每一個響應者確定其是否要處理事件或者是通過nextResponder方法將其傳遞給下一個響應者。這一過程一直持續到找到能處理事件的響應者對象或者最終沒有找到響應者。

參考地址

http://southpeak.github.io/blog/2015/03/07/uiresponder/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM