iOS 響應(yīng)者鏈

摘要

觸摸事件的傳遞虱疏,事件的響應(yīng)

事件的產(chǎn)生

  • 當(dāng)一個觸摸事件發(fā)生后,系統(tǒng)首先會把該事件加入一個待處理的事件隊列。UIApplication會首先處理最先加入隊列的事件擎椰。換句話說UIApplication是事件處理的第一個對象逻住。
  • UIApplication將事件傳遞給keyWindow
  • keyWindow從視圖層級中找到合適的事件處理視圖钟哥。
Paste_Image.png

怎么在視圖層級中找到合適的視圖

view有三種情況不響應(yīng)觸摸事件。

  • hiden
  • userInteractionEnabled
  • alpha < 0.01

找到合適視圖的具體過程

  • 最頂層的視圖及keyWindow是否接受觸摸事件瞎访。
  • 父視圖沒有hiden腻贰,userInteractionEnabled!=NO扒秸,alpha > 0.01并且觸摸區(qū)域在父視圖之內(nèi)播演。
  • 如果父視圖中的subViews不為空,對subViews中的每個view執(zhí)行步驟2同樣的操作鸦采。
  • 如果父視圖沒有subView或者subViews中的每個view都不能處理該觸摸事件宾巍,則父視圖是最終找到的view。

真?zhèn)€過程就是從最頂層的視圖開始通過遞歸找到最終的的合適的視圖渔伯。

hitTest

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{

view使用hitTest檢測自己是不是應(yīng)該響應(yīng)改觸摸或者改event傳遞給子視圖去檢測顶霞。
里邊使用了遞歸。

下邊我們自己實現(xiàn)的一個重寫的hitTest方法锣吼。

#import "WYPResponderView.h"

@implementation WYPResponderView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    //輸出tag
    NSLog(@"******%ld****",self.tag);
    if (self.userInteractionEnabled == NO || self.hidden == YES ||  self.alpha <= 0.01) {
        return nil;
    };
    if ([self pointInside:point withEvent:event] == NO) return nil;
    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 *foundView = [childView hitTest:childP withEvent:event];
        if (foundView) {
            return foundView;
        }
    }
    return self;
}

@end

我們可以檢測下上述代碼的正確性并且跟不重寫hitTest方法的結(jié)果比較下选浑。

創(chuàng)建幾個視圖,并且給每個視圖設(shè)置不同的tag玄叠。

- (UIView *)generateView
{
    WYPResponderView * mainView = [[WYPResponderView alloc] initWithFrame:CGRectMake(0, 64, SCREEN_WIDTH, SCREEN_HEIGHT - 64)];
    mainView.backgroundColor = [UIColor redColor];
    mainView.tag = 0;
    [self.view addSubview:mainView];
    
    WYPResponderView *view1 = [[WYPResponderView alloc] initWithFrame:CGRectMake(20, 30, SCREEN_WIDTH - 80, 250)];
    view1.backgroundColor = [UIColor greenColor];
    view1.tag = 1;
    [mainView addSubview:view1];
    
    WYPResponderView *view2 = [[WYPResponderView alloc] initWithFrame:CGRectMake(20, 300, SCREEN_WIDTH - 80, 250)];
    view2.backgroundColor = [UIColor blueColor];
    [mainView addSubview:view2];
    view2.tag = 2;
    
    
    WYPResponderView *view1_1 = [[WYPResponderView alloc] initWithFrame:CGRectMake(10, 10, SCREEN_WIDTH - 80 - 20, 100)];
    view1_1.backgroundColor = [UIColor grayColor];
    view1_1.tag = 3;
    [view1 addSubview:view1_1];
    
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 10, 50, 50)];
    button.userInteractionEnabled = NO;
    [button addTarget:self action:@selector(XX) forControlEvents:UIControlEventTouchDown];
    button.backgroundColor = [UIColor purpleColor];
    
    [view1_1 addSubview:button];
    
    WYPResponderView *view1_2 = [[WYPResponderView alloc] initWithFrame:CGRectMake(10, 130, SCREEN_WIDTH - 80 - 20, 100)];
    view1_2.backgroundColor = [UIColor darkGrayColor];
    view1_2.tag = 4;
    [view1 addSubview:view1_2];
    
    
    WYPResponderView *view2_1 = [[WYPResponderView alloc] initWithFrame:CGRectMake(10, 10, SCREEN_WIDTH - 80 - 20, 50)];
    view2_1.backgroundColor  = [UIColor grayColor];
    view2_1.tag = 5;
    [view2 addSubview:view2_1];
    
    UIView *view2_2 = [[WYPResponderView alloc] initWithFrame:CGRectMake(10, 70, SCREEN_WIDTH - 80 - 20, 170)];
    view2_2.backgroundColor = [UIColor yellowColor];
    view2_2.tag = 6;
    [view2 addSubview:view2_2];
    
    UIView *view2_2_1 = [[UIView alloc] initWithFrame:CGRectMake(20, 20, SCREEN_WIDTH - 150, 100)];
    view2_2_1.backgroundColor = [UIColor purpleColor];
    view2_2_1.tag = 7;
    [view2_2 addSubview:view2_2_1];
    
    return mainView;
}

界面的最終呈現(xiàn)古徒。

Paste_Image.png

點擊view2_2_1時的hitTest過程

Paste_Image.png

如果我們修改hitTest方法如下,在默認(rèn)的hitTest方法上輸出一段內(nèi)容读恃。

Paste_Image.png

再次點擊下view2_2_1
可以看到輸出跟我們重寫hitTest檢測過程是一樣的隧膘。

事件的響應(yīng)

可以用一張?zhí)O果的官方圖說明。

Paste_Image.png

如果我們找到合適的view之后寺惫,則根據(jù)view的touchesBegan方法判斷view是否要處理該事件疹吃,如果不處理則將事件拋給下一個響應(yīng)者去處理。touchesBegan的默認(rèn)方法就是傳遞給下一個響應(yīng)者西雀。

如何找到下一個響應(yīng)者

  • 如果當(dāng)前view是控制器的view萨驶,那么控制器就是上一個響應(yīng)者,事件就傳遞給控制器艇肴;如果當(dāng)前view不是控制器的view腔呜,那么父視圖就是當(dāng)前view的上一個響應(yīng)者叁温,事件就傳遞給它的父視圖
  • 在視圖層次結(jié)構(gòu)的最頂級視圖,如果也不能處理收到的事件或消息核畴,則其將事件或消息傳遞給window對象進(jìn)行處理
  • 如果window對象也不處理膝但,則其將事件或消息傳遞給UIApplication對象
  • 如果UIApplication也不能處理該事件或消息,則將其丟棄
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末膛檀,一起剝皮案震驚了整個濱河市锰镀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌咖刃,老刑警劉巖泳炉,帶你破解...
    沈念sama閱讀 212,294評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異嚎杨,居然都是意外死亡花鹅,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,493評論 3 385
  • 文/潘曉璐 我一進(jìn)店門枫浙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刨肃,“玉大人,你說我怎么就攤上這事箩帚≌嬗眩” “怎么了?”我有些...
    開封第一講書人閱讀 157,790評論 0 348
  • 文/不壞的土叔 我叫張陵紧帕,是天一觀的道長盔然。 經(jīng)常有香客問我,道長是嗜,這世上最難降的妖魔是什么愈案? 我笑而不...
    開封第一講書人閱讀 56,595評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮鹅搪,結(jié)果婚禮上站绪,老公的妹妹穿的比我還像新娘。我一直安慰自己丽柿,他們只是感情好恢准,可當(dāng)我...
    茶點故事閱讀 65,718評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著甫题,像睡著了一般顷歌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上幔睬,一...
    開封第一講書人閱讀 49,906評論 1 290
  • 那天,我揣著相機與錄音芹扭,去河邊找鬼麻顶。 笑死赦抖,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的辅肾。 我是一名探鬼主播队萤,決...
    沈念sama閱讀 39,053評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼矫钓!你這毒婦竟也來了要尔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,797評論 0 268
  • 序言:老撾萬榮一對情侶失蹤新娜,失蹤者是張志新(化名)和其女友劉穎赵辕,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體概龄,經(jīng)...
    沈念sama閱讀 44,250評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡还惠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,570評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了私杜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚕键。...
    茶點故事閱讀 38,711評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖衰粹,靈堂內(nèi)的尸體忽然破棺而出锣光,到底是詐尸還是另有隱情,我是刑警寧澤铝耻,帶...
    沈念sama閱讀 34,388評論 4 332
  • 正文 年R本政府宣布誊爹,位于F島的核電站,受9級特大地震影響田篇,放射性物質(zhì)發(fā)生泄漏替废。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,018評論 3 316
  • 文/蒙蒙 一泊柬、第九天 我趴在偏房一處隱蔽的房頂上張望椎镣。 院中可真熱鬧,春花似錦兽赁、人聲如沸状答。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,796評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惊科。三九已至,卻和暖如春亮钦,著一層夾襖步出監(jiān)牢的瞬間馆截,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,023評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蜡娶,地道東北人混卵。 一個月前我還...
    沈念sama閱讀 46,461評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像窖张,于是被迫代替她去往敵國和親幕随。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,595評論 2 350

推薦閱讀更多精彩內(nèi)容