響應(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)以及工作中如何使用恐怕還是一頭霧水

點(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

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

前提按鈕在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;
}