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