響應(yīng)者鏈條

響應(yīng)者鏈條:是由多個(gè)響應(yīng)者對(duì)象連接起來(lái)的鏈條

作用:能很清楚的看見(jiàn)每個(gè)響應(yīng)者之間的聯(lián)系,并且可以讓一個(gè)事件多個(gè)對(duì)象處理

響應(yīng)者對(duì)象:能處理事件的對(duì)象

iOS中的事件分為三大類型

三大事件

響應(yīng)者對(duì)象

  • 只要繼承了UIResponder的對(duì)象才能接收并處理事件,我們稱之為“響應(yīng)者對(duì)象”
  • UIApplication、UIViewController、UIView都繼承自UIResponder,因此它們都是響應(yīng)者對(duì)象,都能夠接收并處理事件
  • UIResponder內(nèi)部提供了以下方法來(lái)處理事件
觸摸事件
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

加速計(jì)事件
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event;

遠(yuǎn)程控制事件
- (void)remoteControlReceivedWithEvent:(UIEvent *)event;

事件的產(chǎn)生和傳遞

  • 發(fā)生觸摸事件后,系統(tǒng)會(huì)將該事件加入到一個(gè)由UIApplication管理的事件隊(duì)列中

  • UIApplication會(huì)從事件隊(duì)列中取出最前面的事件,并將事件發(fā)送給應(yīng)用程序的主窗口(KeyWindow)

  • 主窗口會(huì)在視圖層次結(jié)構(gòu)中找到一個(gè)最合適的視圖來(lái)處理觸摸事件,這也是整個(gè)事件處理過(guò)程的第一步

  • 找到合適的視圖控件后,就會(huì)調(diào)用視圖控件的touchs方法來(lái)作事件處理

事件傳遞示例

以下開(kāi)起來(lái)比較直觀,但系統(tǒng)如何實(shí)現(xiàn)以及工作中如何使用恐怕還是一頭霧水


Paste_Image.png

點(diǎn)擊了綠色的view:
UIApplication -> UIWindow -> 白色 -> 綠色
點(diǎn)擊了藍(lán)色的view:
UIApplication -> UIWindow -> 白色 -> 橙色 -> 藍(lán)色
點(diǎn)擊了黃色的view:
UIApplication -> UIWindow -> 白色 -> 橙色 -> 藍(lán)色 -> 黃色

接下來(lái)分析事件是如何傳遞與響應(yīng)的

事件傳遞過(guò)程

UIApplication --> UIWindow --> ViewController-->subViews -->遞歸找到最適合處理事件的控件

so 問(wèn)題來(lái)了 如何找到最合適的View?
兩個(gè)判斷標(biāo)準(zhǔn)符,1.自己是否能接受觸摸事件 2. 觸摸點(diǎn)是否在自己身上?
不符合:證明你不是哦
符合:也不見(jiàn)的是 ,或許你的子控件比你更加合適 所以利用遞歸找到最適合處理事件的那個(gè)子控件 大千世界 茫茫人海 談何容易 (后面的是廢話)

事件響應(yīng)過(guò)程

如上所訴,假設(shè)已經(jīng)找到了最適合View 那么就調(diào)用View的touchs方法來(lái)處理這個(gè)事件吧,ok 響應(yīng)結(jié)束了 ~~

so 問(wèn)題來(lái)了 最合適的View不處理事件呢?
現(xiàn)實(shí)中會(huì)怎樣? 兒子犯事了不敢承擔(dān)一定會(huì)去找他Dad,比如李天一這水貨,是吧
ios 也一樣 會(huì)找到這個(gè)View的SuperView, SuperView不處理 會(huì)找 SuperView的SuperView,然后UIWindow->UIResponder->UIApplication

so 問(wèn)題來(lái)了 UIApplication也不處理 會(huì)怎樣?
事件會(huì)從UIApplication的隊(duì)列中移除

隊(duì)列 與棧有何區(qū)別
隊(duì)列:先進(jìn)先出 棧:先進(jìn)后出

最后來(lái)兩張官方的示意圖 至少可以得出一個(gè)結(jié)論 在事件響應(yīng)的過(guò)程中,View在響應(yīng)給SuperView的同時(shí)會(huì)有一個(gè)判斷,判斷自己是不是控制器的View

是:把事件丟給控制器
不是:繼續(xù)找SuperView

Paste_Image.png

hitTest方法練習(xí)

前面在事件傳遞的過(guò)程中提到View怎么判斷觸摸點(diǎn)在不在自己身上呢?
就是通過(guò)hitTest方法
開(kāi)發(fā)中遇到的類似案例分析

Paste_Image.png

前提按鈕在greenView下面 并非greenView的子控件
如何在按鈕被擋住的情況下 ,讓按鈕同樣能夠接受處理事件呢?
介紹一種方法 也許還有更好的
在greenView調(diào)用hitTest方法尋找最合適的View的同時(shí) 如果點(diǎn)在了按鈕的區(qū)域 ,即使觸摸點(diǎn)并不在按鈕上面 我也認(rèn)定按鈕就是最合適的控件 讓按鈕來(lái)處理事件
我創(chuàng)建greenView繼承自UIView來(lái)管理綠色view
上代碼:

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    //  轉(zhuǎn)化為按鈕上的坐標(biāo)
     CGPoint btnPoint = [self convertPoint:point toView:self.btn];
    
    //   判斷在不在按鈕上面
    if ([self.btn pointInside:btnPoint withEvent:event]) {
        return  self.btn;     
    }
    // 如果不在按鈕的區(qū)域  那么返回greenView為最合適的控件
    return self;
}
最后編輯于
?著作權(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)容

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