1. 程式人生 > >IOS 開發 手勢 及事件傳遞機理

IOS 開發 手勢 及事件傳遞機理

iOS手勢是ios開發不可或缺的一部分,但對於ios的手勢及事件相應機理大家並不知道,所以今天給大家講一講ios的事件相應機理

首先,ios的事件傳遞是依靠“事件鏈”傳遞的,當傳遞到鏈的某一個鏈環上的物件處理了這個事件,事件就停止傳遞。那麼事件鏈是神馬東西?

         事件鏈是由一組UIResponder(能夠響應時間的基類)組成的物件,當然有事件頭和事件尾,事件從頭開始傳遞的,挨個詢問是否處理當前事件。處理的話,就停止傳遞。

對於一個APP的“事件鏈”是如何建立的,建立需要什麼東西

      我們先說app的結構,一般的app是先生成一個APPdelegate 和一個application,然後加window,在加rootview,在加其他的view如下圖

                                                   

                                                                                                                          圖1

從圖中可以看出,app的生成次序,先是appdegate 和UIapplication,然後是window ,下來是各種view,而事件鏈也是在這種結構的基礎上鍊接起來的,形成了一個樹形結構。

從圖中可以看出紅色的標號和箭頭,這個是事件鏈的順序。那麼事件鏈是如何產生的呢,有以下兩種情況。

1.addsubview,將一個普通的view B加到 A上 那麼B的nextresponder(下一個響應者) 就被賦值為A。

2.如果一個veiw不是普通的view,它是某個viewcontroller的根veiw,例如圖中的A,A的nextresponder在A從初始化完後就賦值為viewControllerA。然後當A被addsubview到rootview的時候,Controller A的nextresponder被複製為rootview。

事件鏈的構建不是統一在某一個地方一次構建,而是當產生addsubview時或者在viewController 初始化view時就會觸發。觸發的僅僅是兩個物件,superview和 subview,或者是superview和subview的viewcontroller

既然事件鏈是一個樹形結構,那麼事件也就不能view的兄弟之間傳遞。

補充,UIApplication的nextresponder是APPdelete

講完事件鏈,那麼下來事件是如何傳遞的。

首先,當用戶觸控時,UIKit先建立一個事件物件,加到事件佇列中去,然後UIAPPlication從中取出來,然後來確定事件鏈,然後依次詢問處理。

如何確定事件鏈。

有個hittesting過程。如下

首先先找到window ,

1.呼叫hitTest:withEvent:,hitTest:withEvent:先呼叫pointInside:withEvent:來判斷事件是否發生在自己的區域內

2.如果返回YES,那麼就從window的每個subview開始呼叫1過程。然後一層一層呼叫下去找到最頂部的view。

當然了hitTest:withEvent:在除了pointInside:withEvent:同時,還會參考view的userinteractionenabled和view的隱藏屬性及alpha值,當view隱藏,或者userinteractionenabled為NO,或者alpha小於0.01, hitTest:withEvent:會返回NO。比如說view A 和view B,如下圖

                                                                                         

                                                                                                                                 圖2

A和B的superview 首先會調hitTest:withEvent:在B上,發現B隱藏,或者userinteractionenabled為NO,或者alpha小於0.01,那麼它就放棄了B,轉而檢查A。

以上就是確定事件鏈,然後傳遞就很簡單了。但是有了手勢以後,稍微複雜了點。

首先,我們每個手勢,其實是一系列的UIEvent。

1,每次傳遞其中有一個,他會從事件鏈的最前面開始傳遞,先講event傳遞給事件鏈頂部的View的手勢們。然後看有沒有識別的,如果沒有就繼續到下一個響應者的手勢們,如果立即識別,那麼就停止傳遞。如果傳遞了整個鏈,還沒有發現有識別的,怎麼辦呢。別以為事件就丟掉了,事件會從回到鏈的最前端,然後開始找第一個實現touch(touchbegin,touchend,等等)的view進行識別,然後停止本次傳遞。

2.從事件中再取出一個,繼續進行1過程。最終到沒有事件位置。

以上就算事件的傳遞和識別的整個過程。

對於手勢的引數設定及特殊viewdui時間傳遞處理待續