題記:只要努力,凡事總會(huì)有轉(zhuǎn)機(jī)抱慌。今天復(fù)習(xí)的時(shí)iOS中的響應(yīng)者鏈條和事件的分發(fā),二者存在一定的聯(lián)系眨猎,理解一下原理抑进,對以后編程開發(fā)都會(huì)有幫助的,這些并不難理解睡陪,關(guān)鍵是理解之后要記得住寺渗。
1.什么是事件的響應(yīng)者
只要繼承了UIResponder
的對象就可以作為事件的響應(yīng)者,下面看一下 UIResponder
及其子類的繼承關(guān)系:
其中AppDelegate
類是創(chuàng)建一個(gè)iOS項(xiàng)目時(shí)自動(dòng)創(chuàng)建的繼承UIResponder
的應(yīng)用程序委托類兰迫,記得不太清的同學(xué)可以簡單看一下面的代碼:
// 接口文件
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
// 實(shí)現(xiàn)文件
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {}
- (void)applicationDidEnterBackground:(UIApplication *)application {}
- (void)applicationWillEnterForeground:(UIApplication *)application {}
- (void)applicationDidBecomeActive:(UIApplication *)application {}
- (void)applicationWillTerminate:(UIApplication *)application {}
@end
2. 什么是第一響應(yīng)者
與用戶交互的控件就是第一響應(yīng)者信殊,它將作為響應(yīng)者鏈的開始,事件首先發(fā)送給第一響應(yīng)者汁果,然后再依次傳遞下去涡拘,直到該事件被某個(gè)響應(yīng)者處理。
3. 響應(yīng)者鏈
如果當(dāng)前響應(yīng)者無法響應(yīng)用戶事件据德,它將繼續(xù)向上傳遞鳄乏,直到找到該響應(yīng)者,這個(gè)傳遞過程形成了一條有規(guī)律的鏈條棘利,組成了響應(yīng)者鏈橱野,如下圖:
如果一直找到AppDelegate類還是無法響應(yīng)用戶事件,那么這個(gè)事件將無法被響應(yīng)善玫,但如果在響應(yīng)者鏈上傳遞的過程中水援,有某個(gè)響應(yīng)者對該傳遞的事件有響應(yīng),該傳遞過程將立即停止蝌焚。
4. 事件分發(fā)
- 當(dāng)一個(gè)觸摸事件發(fā)生裹唆,首先接收到事件的對象是UIApplication
- 將事件放入U(xiǎn)IApplication的活動(dòng)隊(duì)列中
- UIApplication的單例對象,再從活動(dòng)隊(duì)列取出該事件只洒,并傳遞給UIWindow
- UIWindow的對象將調(diào)用
-(nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;
方法-
在這個(gè)方法中對其下一層的每一個(gè)視圖調(diào)用
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;
方法许帐,用于判斷當(dāng)前點(diǎn)擊的點(diǎn)是否位于當(dāng)前視圖中(1)若返回NO,則表示不在當(dāng)前視圖中毕谴,
-(nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;
方法返回nil;(2)若返回YES成畦,則說明該觸摸事件發(fā)生在當(dāng)前視圖,然后當(dāng)前視圖再調(diào)用
-(nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;方法
;(3)重復(fù)上述過程涝开,直到
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;
方法返回YES循帐,并使用它調(diào)用-(nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;
方法返回nil的時(shí)候,表示此視圖就是這個(gè)觸摸事的第一響應(yīng)者舀武。
-
5.導(dǎo)致響應(yīng)者鏈條斷掉的幾種可能
- 不能響應(yīng)觸摸事件 userInteractionEnable = NO;
- 這個(gè)要響應(yīng)事件的視圖被隱藏掉了拄养,一種是hidden屬性設(shè)置為 YES了,另一種是這個(gè)圖層的透明度alpha被設(shè)置為 0-0.1之間的值(0.1是我在模擬器中試出來的值);
- 要響應(yīng)事件的視圖被其他視圖B遮住了银舱,相信這個(gè)一般很容易被發(fā)現(xiàn)瘪匿,需要說明的是當(dāng)這個(gè)其他視圖B的透明度在0-0.1之間的時(shí)候跛梗,這個(gè)響應(yīng)時(shí)間還是可以傳遞到“要響應(yīng)事件的視圖”上去的,所以當(dāng)“要響應(yīng)事件的視圖”未響應(yīng)你設(shè)定的響應(yīng)事件棋弥,檢查一下是否有這樣的一個(gè)視圖B覆蓋在上面核偿,且它的透明度大于0.1;
這里要感謝 紙飛機(jī)波音747的提問顽染,和iPhone貼膜小哥對回答的補(bǔ)充