iOS事件傳遞和響應鏈

一、事件傳遞機制

在iOS中,只有繼承于UIResponder的子類,才可以處理事件。

1.當iOS程序中發生觸摸事件后,系統會將事件加入到UIApplication管理的一個任務隊列中
2.UIApplication將處于任務隊列最前端的事件向下分發。即UIWindow。
3.UIWindow將事件向下分發,即UIView。
4.UIView首先看自己是否能處理事件,觸摸點是否在自己身上。如果能,那么繼續尋找子視圖。
5.遍歷子控件,重復3,4兩步。如果沒有在子控件找到觸摸點,那么自己就是事件處理者。
6.如果自己不能處理觸摸響應,那么不做任何處理。

事件分發傳遞,以下三種情況是不做處理的:

1.alpha < 0.01
2.userInteractionEnabled = NO
3.hidden = YES
若父視圖事件不做處理,(以上三種情況),那么子視圖也不會傳遞事件,改事件傳遞被廢棄。

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

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

1.通過重寫hitTest方法,可將點擊的點移動到子view。
2.重寫pointInside方法,可擴大按鈕的點擊區域。

eg: 按鈕的點擊區域重寫,小于44*44做處理,大于不處理
下面示例是定義一個button的可點擊區域
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {

    CGRect bounds = self.bounds;
    CGFloat widthDelta = MAX(44 - bounds.size.width, 0);
    CGFloat heightDelta = MAX(44 - bounds.size.height, 0);
    bounds = CGRectInset(bounds, -0.5 * widthDelta, -0.5 * heightDelta);
    return CGRectContainsPoint(bounds, point);
}

二、事件響應鏈

1.事件響應鏈的響應剛好和事件傳遞相反,事件傳遞是從UIApplication管理起點,逐級向下傳遞。而響應鏈則從下向上傳遞。響應鏈是通過nextResponder屬性組成的一個鏈表,點擊的view有 superView,nextResponder就是superView;


image.png

最有機會處理事件的就是通過事件傳遞找到的 first responder,如果沒有進行處理,就會沿著事件響應鏈傳遞給下一個響應者 nextResponder,一直追溯到最上層 UIApplication。若都沒有進行處理,就丟棄事件。
處理事件

  • (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
  • (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
  • (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
  • (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;

對于觸摸事件,系統提供了上面四種方法來處理。如果重寫了上述方法,那么事件就會在此中斷,并且不再沿著事件響應鏈進行傳遞;如果需要繼續進行傳遞,則需要調用 super 方法。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。