事件的響應(UIResponder)、touch、UIGestureRecognizer

ios 中事件的處理接口或者說協議是由UIResponder 定義的。

最主要的事件就是touch事件,touch事件是 UIAapplacation 對象 runloop 檢測到並封裝的。UIApplaction 對象封裝好後將事件傳遞給UIWindeow對象。touch 事件的處理分爲兩步,第一個步是找到 該touch 所對應的 view,即touch 是那個在那個view上的;第二是步是找到處理該該事件的對象。

第一步的實現,直接調用 UIWindow的

none

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;

方法,該方法 會返回 以調用者爲 根的view 樹 中touch 事件 所對應的view。該方法的實現是調用所有子view的

none

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;

然後返回 yes 的 子 view 調用

none

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;

這樣遞歸調用直到不存在 葉子 view ,然後返回該View。需要注意的這個遞歸調用每次傳遞的 point 值實景過轉換的。實在 相應view座標系下的position。

需要說明的是 view 的UIinterfaceEnable 和 存在 gesture recognize 的 會影像這個過程的進行。 UIinterfaceEnable 爲no 的 ,gesture recognize  的 canceltouchinview 爲yes 的 則該 過程不會 進行下去。UIinterfaceEnable 爲no 的  則 super view 不會 hittest 這樣的子view。gesture recognize  的 canceltouchinview 爲yes 的 view 不會 hittest 子view。

第二步是找到處理該事件的對象。從第一步找到的View開始 沿着 reponder chain 將 事件傳遞下去。需要注意的是responder chain 中某一個對象可以 不將 事件 繼續往下傳,那麼 responder chain 下面的對象就不會處理該對象。常見的 chain 是 view –> viewController –>super view –> superview controller —> super super view —> supersuperview controller 最後到rootcontroller 然後到window。需要注意的是  viewcontroller的下一個 responder 是 superview。ios 如果view congroller 的使用不是 按照tabbar navigationbar viewcongroller的方法來使用,就可能產生 responder chain 不對的情況。 (直接將view congroller 的 view addsubiew 到其他view 上)

從上面我們可以看出 一個事件 可以讓多個對象同時 知道 並進行處理。這個chain 的實現 的接口就是

none

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

該四個方法的默認實現是調用 nextresponder 的該四個方法。也就是說如果不復寫這幾個方法,則事件會最終傳遞到 window,window 的處理一般是直接丟棄。

下面來說說UIGestureRecognizer:

UIGestureRecognizer 對象是添加到 view 對象上面的,當view 收到 hittest 時候,該GestureRecognizer 會被通知到。GestureRecognizer 也是 有並封裝了 上面四種方法,然後根據 touch 事件的時間 位置 特徵 來 進行 特定的動作。ios系統中提供了 一些UIGestureRecognizer 的子類,這些子類就是處理特定的 touch 序列的。

UIGestureRecognizer 提供了一些代理來 方便的封裝了 對上面四種 方法的實現進行 配置。如下面的方法 定義了 是否 根據情況 將 touch 事件 加入到事件序列中,生成響應的動作。

none

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;

除了touch 事件的 其他事件的 處理 需要引入 第一響應者,這些事件包括

none

程序中只有一個第一響應者。第一響應者 相關的 函數是

none

- (BOOL)canBecomeFirstResponder;    // default is NO

- (BOOL)becomeFirstResponder;

- (BOOL)canResignFirstResponder;    // default is YES

- (BOOL)resignFirstResponder;

- (BOOL)isFirstResponder;

對象通過 – (BOOL)becomeFirstResponder; 來向程序 將自己(或者別的對象)註冊成第一響應者。被註冊者通過- (BOOL)canBecomeFirstResponder;方法來表示自己是不是原因 成爲第一響應者。    需要第一響應者的事件到來後,事件會交給第一響應者,然後第一響應者沿着 responder chain 將事件傳遞下去。motion 事件的 responder chain 是由

none

方法來實現的,該方法 同 touch responder chain 的方法 實現相同,如果沒有對象處理,則傳遞給 UIApplication 對象,然後丟棄。

(轉自:http://dcm19872007.blog.163.com/blog/static/865193742013018112558478/)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章