一娇斑、響應者對象
App使用響應者對象來處理觸摸事件。響應者對象的類是UIResponder材部,所有繼承于UIResponder的子類的實例都是響應者對象毫缆。這些子類包括常見的UIView、UIViewController乐导、UIWindow苦丁、UIApplication等。
二物臂、查找第一響應者
用戶觸摸屏幕后旺拉,系統(tǒng)會將觸摸事件封裝成一個UIEvent對象發(fā)送給UIApplication對象产上。UIApplication會將UIEvent對象加入到事件隊列中。UIApplication事件隊列遵循先進先出的原則蛾狗,會將隊列最前面的事件取出來發(fā)送給UIWindow晋涣。
然而并不是所有UIResponder對象都能成為響應者,如果UIResponder對象出現(xiàn)以下幾種情況沉桌,則不能響應事件:
1谢鹊、userInteractionEnabled == NO;
2、hidden == YES;
3留凭、alpha <= 0.01;
4佃扼、調(diào)用pointInside:point withEvent:event方法返回NO
UIWindow接收到觸摸事件后, 會通過hitTest:withEvent:方法查找第一響應者蔼夜,該方法會返回第一響應者兼耀,查找過程如下:
1、判斷自身是否能響應事件(方法在上面)挎扰,如果不能,則hitTest:withEvent:方法返回nil巢音,此視圖不能響應事件遵倦。
2、如果可以響應事件官撼,則會從后向前遍歷子控件梧躺,子控件也會調(diào)用hitTest:withEvent:查找他的視圖層級中的第一響應者。
3傲绣、如果有子視圖可以響應事件掠哥,則返回子視圖,如果沒有秃诵,則返回自身续搀。
hitTest:withEvent:方法的內(nèi)部實現(xiàn)大概是這樣的
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
BOOL isHit = [self isPossibleResponder:point withEvent:event];
if (isHit == NO) return nil;
for (int i = self.subviews.count - 1;i >= 0;i--) {
UIView *subView = self.subviews[i];
UIView *hitTestView = [subView hitTest:point withEvent:event];
if (hitTestView) return hitTestView;
}
return self;
}
- (BOOL)isPossibleFirstResponder:(CGPoint)point withEvent:(UIEvent *)event{
if (self.userInteractionEnabled == NO||
self.hidden == YES||
self.alpha <= 0.01) return NO;
return [self pointInside:point withEvent:event];
}
當然,你也可以通過重寫這個方法返回你所指定的響應者對象菠净。
三禁舷、響應者鏈
系統(tǒng)通過上面的方法可以查找到第一響應者,但第一響應者只是可以響應事件毅往,并不代表它一定會響應這個事件牵咙。如果第一響應者不響應事件,它會把事件沿著響應者鏈向上傳遞攀唯。響應者對象有一個屬性nextResponder洁桌,即當前響應者對象在響應者鏈上的下一環(huán),在當前響應者對象不響應事件的情況下侯嘀,系統(tǒng)會將事件傳遞給nextResponder另凌。你可以重寫get方法返回指定的nextResponder谱轨。如果不重寫,系統(tǒng)會默認指定了一些響應者對象的nextResponder
- UIView:如果View是控制器的主View途茫,則nextResponder就是控制器碟嘴。否則,nextResponder是View的superView囊卜。
- UIViewController:
- 如果UIViewController是UIWindow的根控制器娜扇,那么它的nextResponder是Window;
- 如果UIViewController是通過presentViewController方法彈出來的栅组,那么它的nextResponder是彈它出來的那個控制器雀瓢;
- 如果不是以上兩種情況,那么它的nextResponder是它的主View的superView玉掸。
- UIWindow:nextResponder是UIApplication對象刃麸。
- UIApplication:如果app delegate對象是響應者對象,且不是UIView司浪、UIViewController或者UIApplication本身泊业,那么UIApplication的nextResponder是app delegate。
如果事件沿著響應者鏈傳遞到UIApplication或者app delegate都沒有響應者對象響應啊易,那么這個事件就會被丟棄吁伺。
四、手勢
UIView的手勢的響應優(yōu)先級高于UIView本身租谈。UIView收到UIEvent后篮奄,會優(yōu)先交給綁定到它身上的手勢進行識別,如果識別不出來割去,才會交由UIView響應窟却。如果UIView不響應,則會沿著響應者鏈向上傳遞呻逆。