iOS 響應(yīng)者鏈

響應(yīng)者鏈顧名思義就是由一系列能夠響應(yīng)事件的響應(yīng)者對(duì)象組成的一個(gè)層式結(jié)構(gòu)。我們把具有響應(yīng)和處理事件能力的對(duì)象稱為響應(yīng)者對(duì)象。

  • 事件:有三種
    1、Touch Events,點(diǎn)擊事件;
    2、Motion Events,移動(dòng)事件,比如監(jiān)聽加速器、陀螺儀 產(chǎn)生的事件;
    3、Remote Control Events,遠(yuǎn)程控制事件, 比如耳機(jī),可以控制你的音量、播放音樂。

  • 響應(yīng)對(duì)象
    UIResponder 是所有具有響應(yīng)對(duì)象的基類,我們熟悉的UIApplication、UIViewController、UIWindow 和所有繼承自UIView的 UIKit 都直接或間接的繼承自 UIResponder,所以它們的實(shí)例都是可以構(gòu)成響應(yīng)者鏈的響應(yīng)對(duì)象。

當(dāng)用戶點(diǎn)擊屏幕的時(shí)候,觸摸事件通過(guò) hitTest:withEvent: 來(lái)確定first Response,該方法接收參數(shù)CGPoint 和 UIEvent,并從底層開始按照subView的順序測(cè)試該CGPoint在哪個(gè)View上,如果在該View上,則繼續(xù)測(cè)試是否在View的subview上。

舉個(gè)??
例子.png

假設(shè)用戶觸摸了圖中的view E。iOS通過(guò)如下順序查找hit-test view
1.觸摸點(diǎn)在A里面,因此檢測(cè)子view B和C
2.觸摸點(diǎn)不在B里面,但是在C里面。因此檢測(cè)C的子View D和E。
3.觸摸點(diǎn)不在D里面,但是在E里面,并且E是在最外層的包含觸摸點(diǎn)的view,因此E就是要找的hit-test view

hitTest:withEvent:函數(shù)的實(shí)現(xiàn)代碼:

1.能否自己處理?不能,return nil;
2.點(diǎn)在不在當(dāng)前控件上?沒在,return nil;
3.說(shuō)明能處理觸摸事件,并且在當(dāng)前控件上,是合適的控件,但不一定是最合適的。從后往前遍歷自己的子控件,是否是最合適的控件(包含該觸摸點(diǎn)的View)。如果是,返回該View。
4.說(shuō)明沒找到比自己合適的View,返回自己。

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event的實(shí)現(xiàn):
[objc] view plain copy
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event  
{  
    if (self.hidden || !self.userInteractionEnabled || self.alpha < 0.01)  
    {  
        return nil;  
    }  
    if (![self pointInside:point withEvent:event])  
    {  
        return nil;  
    }  
    __block UIView *hitView = self;  
    [self.subViews enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOLBOOL *stop) {     
  
        CGPoint thePoint = [self convertPoint:point toView:obj];  
  
        UIView *theSubHitView = [obj hitTest:thePoint withEvent:event];  
  
        if (theSubHitView != nil)  
        {  
            hitView = theSubHitView;  
  
            *stop = YES;  
        }  
  
    }];  
  
    return hitView;  
}  
  • 視圖允許接收觸摸事件的條件是:
    視圖不是隱藏的:self.hidden == NO
    視圖是允許交互的:self.userInteractionEnabled ==true
    視圖透明度大于0.01:self.alpha > 0.01
    視圖包含這個(gè)點(diǎn): pointInside:withEvent: ==true

hit-test view和響應(yīng)鏈的概念:當(dāng)一個(gè)事件發(fā)生需要處理時(shí),會(huì)讓合適的對(duì)象去處理。如果是觸摸事件的話,該對(duì)象就是hit-test view。如果是其他事件,該對(duì)象指的就是第一響應(yīng)者(響應(yīng)鏈中)。響應(yīng)鏈?zhǔn)且粋€(gè)比較大的范疇,在觸摸事件中,hit-test view就是響應(yīng)鏈中的第一響應(yīng)者。也就是說(shuō)在觸摸事件中通過(guò)hitTest:withEvent:方法找到的hit-test view就是第一響應(yīng)者。

下圖給出了沿著響應(yīng)鏈傳遞的順序。兩個(gè)圖的區(qū)別是視圖的層次關(guān)系不一樣。響應(yīng)鏈從firstResponse開始接下來(lái)是它的父視圖,如果沒有父視圖直到它的控制器(如果有的話)再到window和application。


響應(yīng)鏈傳遞的順序.png

initial view可能是hit-test view或者是first responder,沒有處理事件。UIkit就會(huì)將該事件傳遞給next responder下一個(gè)響應(yīng)者,每個(gè)響應(yīng)者通過(guò)調(diào)用-nextResponder方法決定是處理該事件還是向響應(yīng)鏈的上層傳遞,直到某個(gè)響應(yīng)者處理了該事件或者沒有響應(yīng)者了為止。

需要注意的是,所有的響應(yīng)鏈都是父子視圖的關(guān)系,如果View A、View C、 VIew E只是視覺上遮蓋了,但是卻不是superview、subview的關(guān)系,則事件是不會(huì)在兩者之間傳遞的.

響應(yīng)者鏈順序如下:

Initial View -> View Controller(如果存在) -> superview -> · ··  -> rootView -> UIWindow -> UIApplication
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、響應(yīng)者鏈(Responder Chain) 先來(lái)說(shuō)說(shuō)響應(yīng)者對(duì)象(Responder Object),顧名思義,...
    像小強(qiáng)一樣活著閱讀 6,948評(píng)論 8 76
  • 1、響應(yīng)鏈的傳遞 Responder一點(diǎn)也不神秘————iOS用戶響應(yīng)者鏈完全剖析(建議全看)看完上面一篇應(yīng)該能完...
    RasonWu閱讀 10,505評(píng)論 3 36
  • 好奇觸摸事件是如何從屏幕轉(zhuǎn)移到APP內(nèi)的?困惑于Cell怎么突然不能點(diǎn)擊了?糾結(jié)于如何實(shí)現(xiàn)這個(gè)奇葩響應(yīng)需求?亦或是...
    Lotheve閱讀 59,425評(píng)論 51 604
  • 當(dāng)你設(shè)計(jì)一個(gè)app的時(shí)候,可能會(huì)有這樣的場(chǎng)景,你想動(dòng)態(tài)的去響應(yīng)一個(gè)事件。例如,在屏幕上的一個(gè)觸摸事件可能在不同的對(duì)...
    007Mango閱讀 20,161評(píng)論 12 40
  • 在iOS開發(fā)中經(jīng)常會(huì)涉及到觸摸事件。本想自己總結(jié)一下,但是遇到了這篇文章,感覺總結(jié)的已經(jīng)很到位,特此轉(zhuǎn)載。作者:L...
    WQ_UESTC閱讀 6,236評(píng)論 4 26

友情鏈接更多精彩內(nèi)容