swift 觸控事件傳遞很難介入控制,除非子類化UIApplication修改 sendEvent(event:)

觸控事件流程

UIGestureRecognizer (高優先) > UIControl(如 UIButton)

整個觸控事件流程分為二個階段,三種事件。


單一個 View 的觸控交互::

  1. 手指觸碰 View
  2. (由下(子)往上(父)傳遞): hitTest(_) → UIView? 判斷 View 是否為第一響應者,如果成立回傳自己,不成立傳遞nil 給父層。
  3. (由下往上確認): hitTest(_) → UIView? 判斷 View 是否為第一響應者,如果成立回傳自己,回傳上一層通知 nil 。
  1. 跟蹤手指運動,劃分動作類型(如: tap, swipe, move 等)
  2. 依照動作依照順序執行物件表中符合的物件事件 ,解釋有點複雜,請看下面偽代碼。
// event is Tap
// view = 第一響應者
// gestureRecognizers : 所有的 gest
// controls: 第一響應者如果為 UIControl的 Controls
// UIGestureRecognizer 階段
// 從已添加 UIGesture 取出最後加入的 tap 事件
// 從已添加 
// 其他運動軌跡以此類推
beginTracking()
touchBegan()

if let gest = gestureRecognizers.lastIndex(where: { $0 === tap } {
   // 執行觸控事件
   gest.launchAction()
   // 檢查是否繼續傳遞 event
    guard !gest.cancelsTouchesInView else { 
       vuew.touchesCancel()
       return
    }
    // UIResponder 與 UIControl 階段
    view.touchesEnded()
    // (if view === UIControl) 
    if  beginTracking {  
         view.endTracking()    
         view.actions.forEach { if $0.event == tap { $0.launchAction() }  }   
       }   
  return 
}
    
 // 無符合 Gesture事件
 // 執行 UIResponder 與 
 view.touchesEnded()
 // (if view === UIControl) 
                                                 
 if  beginTracking() {
    view.endTracking()    
    view.actions.forEach { $0.event == tap { $0.launchAction() } } 
 }
 
 // 如果需要取消追蹤
 if needCancelTrack {
    view.cancelTracking()
}
view raw觸控解說偽代碼.swift hosted with ❤ by GitHub

總結