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
- Motion events—via calls to the UIResponder motion-handling methods described in “Shaking-Motion Events”
- Remote-control events—via calls to the UIResponder method remoteControlReceivedWithEvent:
- Action messages—sent when the user manipulates a control (such as a button or slider) and no target is specified for the action message
- Editing-menu messages—sent when users tap the commands of the editing menu (described in “Displaying and Managing the Edit Menu”)
程序中只有一個第一響應者。第一響應者 相關的 函數是
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/)