前言:面試
不知不覺開發iOS三年之多了,成功的從一個小菜鳥變成了大菜鳥,前些日子面試被問到: iOS中事件傳遞是怎麼樣的,touch事件蘋果是如何收集的? 因爲以前沒有了解過這些原理以及實現.一直本着能用就行.遇到這種問題直接懵逼了.
微信
後來經過閱讀相關文章簡單總結了一下,但願能夠幫助到更多同窗!!!但願共同成長ide
在iOS中凡是繼承自UIResponder的對象都可以接收並處理事件spa
•先說如何會產生touch事件對象
1.觸摸事件(例如點擊,滑動,縮放等)blog
2.加速計事件(例如搖微信一搖,指南針等)繼承
3.遠程控制事件(例如藍牙,wifi)遞歸
1.觸摸事件:隊列
當手指觸摸手機屏幕時,系統會調用view的事件
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event方法
當手指在手機屏幕上移動時,系統會調用view的
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event方法
當手指離開手機屏幕時,系統會調用view的
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event方法
每一個方法中的touches參數是NSSet類型(也就是集合類型),裏邊存放的是一個或多個UITouch對象,當手指觸摸到屏幕時候會建立UITouch對象(一個手指對應一個UITouch對象),每一個UITouch對象中存放的是這個動做的相關信息(觸摸次數,視圖大小,位置,類型等相關信息)
當手指離開屏幕後,集合裏保存的UITouch對象也會隨之銷燬.
那咱們來看看這些動做是怎麼實現的,首先咱們來看事件是怎麼傳遞的
發生觸摸事件後,系統會將該事件加入到一個由UIApplication管理的隊列事件中,UIApplication會從事件隊列中取出最前邊的事件分發下去處理,會先發生給窗口視圖KeyWindow
視圖會一層一層向上尋找最合適的視圖來處理事件.找到合適的視圖後會調用該視圖的Touch方法(也就是上邊說到的touchBegin,touchMove等)去作處理.也就是說該事件傳遞是從父視圖依次向子視圖傳遞的.若是父視圖不可以接收並處理事件,那麼他的子視圖就不能接收並響應事件.
如下幾種狀況View不能接收並響應事件
1.view.userInteractionEnabled = NO;(不可交互)
2.view.hidden = YES;(隱藏)
3.view.alpha <=0.01;(透明度小於等於0.01)
那麼如何找到最合適的視圖?
1.本身自己是否能夠接收事件
2.觸摸點是否在自己範圍內
3.查看本身的子控件是否能夠接收事件
4.查看觸摸到是否在本身的子控件上
5.若是沒有就在本身自己處理
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 這個方法就是用來查找最合適處理事件的方法,和-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event配合使用(判斷觸摸到是否在自身上).
經過上邊的步驟.咱們能夠本身來模擬一下尋找view的實現
最後總結來講一次完整的觸摸事件的傳遞響應過程爲:
UIApplication-->UIWindow-->遞歸找到最合適處理的控件-->控件調用touches方法-->判斷是否實現touches方法-->沒有實現默認會將事件傳遞給上一個響應者-->找到上一個響應者-->找不到方法做廢
最後咱們還可使用響應者鏈找到當前視圖
- (UIViewController *)parentController
{
UIResponder *responder = [self nextResponder];
while (responder) {
if ([responder isKindOfClass:[UIViewController class]]) {
return (UIViewController *)responder;
}
responder = [responder nextResponder];
}
return nil;
}