iOS 事件传递响应链
iOS中加載的時候會先執行main函數
int main(int argc, char * argv[]) {@autoreleasepool {return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));} }根據main函數的參數加載UIApplication->AppDelegate->UIWindow->UIViewController->superView->subViews
關系為:UIApplication.keyWindow.rootViewController.view.subView
?
?
那么,系統是怎么找到接收觸摸事件發生的視圖的?
只通過UIView及其子類查找,調用根視圖的hitTtest:withEvent,其的執行過程如下:
iOS使用hit-testing尋找觸摸的view。 Hit-Testing通過檢查觸摸點是否在關聯的view邊界內,如果在,則遞歸地(recursively)檢查該view的所有子view。在層級上處于lowest(我理解就是離用戶最近的view)且邊界范圍包含觸摸點的view成為hit-test view。確定hit-test view后,它傳遞觸摸事件給該view。
?
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {// 1.判斷當前控件能否接收事件if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) return nil;// 2. 判斷點在不在當前控件if ([self pointInside:point withEvent:event] == NO) return nil;// 3.從后往前遍歷自己的子控件NSInteger count = self.subviews.count;for (NSInteger i = count - 1; i >= 0; i--) {UIView *childView = self.subviews[i];// 把當前控件上的坐標系轉換成子控件上的坐標系CGPoint childP = [self convertPoint:point toView:childView];UIView *fitView = [childView hitTest:childP withEvent:event];if (fitView) { // 尋找到最合適的viewreturn fitView;}}// 循環結束,表示沒有比自己更合適的viewreturn self;}?其中,-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
這個函數的用處是判斷當前的點擊或者觸摸事件的點是否在當前的view中。
它被hitTest:withEvent:調用,通過對每個子視圖調用pointInside:withEvent:決定最終哪個視圖來響應此事件。如果 PointInside:withEvent:返回YES,然后子視圖的繼承樹就會被遍歷(遍歷順序中最先響應的為:與用戶最接近的那個視圖。 it starts from the top-level subview),即子視圖的子視圖繼續調用遞歸這個函數,直到找到可以響應的子視圖(這個子視圖的hitTest:withEvent:會返回self,而不是nil);否則,視圖的繼承樹就會被忽略。
?
?
?
?
?
總結
以上是生活随笔為你收集整理的iOS 事件传递响应链的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PHP|异常的使用,异常子类化的最佳实践
- 下一篇: jps 命令使用