Cocoa Touch事件處理流程 響應者鏈

2022-05-31 22:15:11 字數 2745 閱讀 3064

一、事件分類

對於ios裝置使用者來說,他們操作裝置的方式主要有三種:觸控螢幕、晃動裝置、通過遙控設施控制裝置。對應的事件型別有以下三種:

1、觸屏事件(touch event)

2、運動事件(motion event)

3、遠端控制事件(remote-control event)

今天以觸屏事件(touch event)為例,來說明在cocoa touch框架中,事件的處理流程。首先不得不先介紹響應者鏈這個概念:

二、響應者鏈(responder chain)

先來說說響應者物件(responder object),顧名思義,指的是有響應和處理事件能力的物件。響應者鏈就是由一系列的響應者物件構成的乙個層次結構。

圖一從圖一中可以看到,響應者鏈有以下特點:

1、響應者鏈通常是由檢視(uiview)構成的;

2、乙個檢視的下乙個響應者是它檢視控制器(uiviewcontroller)(如果有的話),然後再轉給它的父檢視(super view);

3、檢視控制器(如果有的話)的下乙個響應者為其管理的檢視的父檢視;

4、單例的視窗(uiwindow)的內容檢視將指向視窗本身作為它的下乙個響應者

需要指出的是,cocoa touch應用不像cocoa應用,它只有乙個uiwindow物件,因此整個響應者鏈要簡單一點;

三、事件分發(event delivery)

第一響應者(first responder)指的是當前接受觸控的響應者物件(通常是乙個uiview物件),即表示當前該物件正在與使用者互動,它是響應者鏈的開端。整個響應者鏈和事件分發的使命都是找出第一響應者。

uiwindow物件以訊息的形式將事件傳送給第一響應者,使其有機會首先處理事件。如果第一響應者沒有進行處理,系統就將事件(通過訊息)傳遞給響應者鏈中的下乙個響應者,看看它是否可以進行處理。

uiwindow例項物件會首先在它的內容檢視上呼叫hittest:withevent:,此方法會在其檢視層級結構中的每個檢視上呼叫pointinside:withevent:(該方法用來判斷點選事件發生的位置是否處於當前檢視範圍內,以確定使用者是不是點選了當前檢視),如果pointinside:withevent:返回yes,則繼續逐級呼叫,直到找到touch操作發生的位置,這個檢視也就是要找的hit-test view。

hittest:withevent:方法的處理流程如下:

首先呼叫當前檢視的pointinside:withevent:方法判斷觸控點是否在當前檢視內;

若返回no,則hittest:withevent:返回nil;

若返回yes,則向當前檢視的所有子檢視(subviews)傳送hittest:withevent:訊息,所有子檢視的遍歷順序是從最頂層檢視一直到到最底層檢視,即從subviews陣列的末尾向前遍歷,直到有子檢視返回非空物件或者全部子檢視遍歷完畢;

若第一次有子檢視返回非空物件,則hittest:withevent:方法返回此物件,處理結束;

如所有子檢視都返回非,則hittest:withevent:方法返回自身(self)。

圖二加入使用者點選了view e,下面結合圖二介紹hit-test view的流程:

1、a是uiwindow的根檢視,因此,uiwindwo物件會首相對a進行hit-test;

2、顯然使用者點選的範圍是在a的範圍內,因此,pointinside:withevent:返回了yes,這時會繼續檢查a的子檢視;

3、這時候會有兩個分支,b和c:

點選的範圍不再b內,因此b分支的pointinside:withevent:返回no,對應的hittest:withevent:返回nil;

點選的範圍在c內,即c的pointinside:withevent:返回yes;

4、這時候有d和e兩個分支:

點選的範圍不再d內,因此d的pointinside:withevent:返回no,對應的hittest:withevent:返回nil;

點選的範圍在e內,即e的pointinside:withevent:返回yes,由於e沒有子檢視(也可以理解成對e的子檢視進行hit-test時返回了nil),因此,e的hittest:withevent:會將e返回,再往回回溯,就是c的hittest:withevent:返回e--->>a的hittest:withevent:返回e。

至此,本次點選事件的第一響應者就通過響應者鏈的事件分發邏輯成功的找到了。

不難看出,這個處理流程有點類似二分搜尋的思想,這樣能以最快的速度,最精確地定位出能響應觸控事件的uiview。

三、說明

2、hittest:withevent:方法將會忽略隱藏(hidden=yes)的檢視,禁止使用者操作(userinteractionenabled=yes)的檢視,以及alpha級別小於0.01(alpha<0.01)的檢視。如果乙個子檢視的區域超過父檢視的bound區域(父檢視的clipstobounds 屬性為no,這樣超過父檢視bound區域的子檢視內容也會顯示),那麼正常情況下對子檢視在父檢視之外區域的觸控操作不會被識別,因為父檢視的pointinside:withevent:方法會返回no,這樣就不會繼續向下遍歷子檢視了。當然,也可以重寫pointinside:withevent:方法來處理這種情況。

3、我們可以重寫hittest:withevent:來達到某些特定的目的,下面的鏈結就是乙個有趣的應用舉例,當然實際應用中很少用到這些。

JS 事件流與事件處理程式

1.事件流 從頁面中接收事件的順序 1.1 ie 事件冒泡流 1.2 netscape 事件捕獲 1.3 dom事件流 事件捕獲階段 事件目標階段 事件冒泡階段 dom2級事件規定 捕獲階段不會涉及目標事件。2.事件處理程式 事件 使用者或者瀏覽器自身執行的 某種動作 事件處理程式 響應某個事件的 ...

JS 事件流與事件處理程式

1.事件流 從頁面中接收事件的順序 1.1 ie 事件冒泡流 1.2 netscape 事件捕獲 1.3 dom事件流 事件捕獲階段 事件目標階段 事件冒泡階段 dom2級事件規定 捕獲階段不會涉及目標事件。2.事件處理程式 事件 使用者或者瀏覽器自身執行的 某種動作 事件處理程式 響應某個事件的 ...

前端的事件流以及事件處理程式

一 事件流 1.事件流 事件流描述的是從頁面中接收事件的順序。ie 的事件流是事件冒泡流,netscape 的事件流是事件捕獲流。2.事件冒泡流 ie 的事件流叫事件冒泡,即事件開始時由最具體的元素 文件中巢狀層次最深的那個節點 接收,然後逐級向上傳播到較為不具體的節點 文件 若點選了頁面中的某個d...