響應鏈及其事件傳遞

觸摸事件處理的詳細過程:

當用戶點擊屏幕後產生一個觸摸事件,經過經過一系列的傳遞過程後,會找到最合適的視圖控件來處理這個事件,找到最合適的視圖之後,就會調用空間的touches那三個方法,這些方法的默認做法是把事件順着響應者鏈條向上傳遞,將事件傳遞給上一個響應者進行處理。

傳遞過程

  1. UIApplication接收到事件,將事件傳遞給Window
  2. Window遍歷subViewshitTest:withEvent:方法,找到點擊區域內合適的視圖來處理事件。
  3. UIView的子視圖也會遍歷其subViewshitTest:withEvent:方法,以此類推。
  4. 直到找到點擊區域內,且處於最上方的視圖,將視圖逐步返回給UIApplication
  5. 在查找第一響應者的過程中,已經形成了一個響應者鏈。
  6. 應用程序會先調用第一響應者處理事件。
  7. 如果第一響應者不能處理事件,則調用其nextResponder方法,一直找響應者鏈中能處理該事件的對象。
  8. 最後到UIApplication後仍然沒有能處理該事件的對象,則該事件被廢棄。

怎麼尋找最合適的view?用到以下的兩個方法。

// 此方法返回的View是本次點擊事件需要的最佳View
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

// 判斷一個點是否落在範圍內
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event

事件傳遞給窗口或控件的後,就調用hitTest:withEvent:方法尋找更合適的view,如果子控件是合適的view,則在子控件再調用hitTest:withEvent:查看子控件是不是合適的view,一直遍歷,直到找到最合適的view,或者廢棄事件。

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if (self.alpha <= 0.01 || self.userInteractionEnabled == NO || self.hidden) {
        return nil;
    }
    
    BOOL inside = [self pointInside:point withEvent:event];
    if (inside) {
        NSArray *subViews = self.subviews;
        // 對子視圖從上向下找
        for (NSInteger i = subViews.count - 1; i >= 0; i--) {
            UIView *subView = subViews[i];
            CGPoint insidePoint = [self convertPoint:point toView:subView];
            UIView *hitView = [subView hitTest:insidePoint withEvent:event];
            if (hitView) {
                return hitView;
            }
        }
        return self;
    }
    return nil;
}

總結:

     1、首先判斷UIControl還是UIResponder;

     2、如果是UIResponder -(從上往下) 響應鏈找到最合適的視圖  ;如果是 UIControl- UIApplication (如果類似view1有btn和tap 則響應btn,如果view1有btn,btn上有tap,則響應tap)

     3、有手勢先手勢,同級的話先看有沒有UIControl。

tips:

1、手勢不參與響應者鏈傳遞事件,但是也通過hitTest的方式查找響應的視圖,手勢和響應者鏈一樣都需要通過hitTest方法來確定響應者鏈的。在UIApplication向響應者鏈派發消息時,只要響應者鏈中存在能夠處理事件的手勢,則手勢響應事件,如果手勢不在響應者鏈中則不能處理事件,處理最合適的view的響應。

2、如果同一視圖有UIGesture和UIButton,會響應UIButton的響應事件;

3、如果同一視圖添加多個UIGesture,只會響應最上面的。

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