iOS面试那些事iOS Developer

iOS 触摸事件与响应理解

2017-04-20  本文已影响55人  Auther丶

参考文章:      
 iOS触摸事件的流动

iOS触摸事件的传递与响应

UIViewController UIApplication UIView 都继承了UIResponder ,可响应以下事件

UIResponder内部提供了以下方法来处理事件触摸事件- (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;

一 触摸事件的产生与传递

找: 从父视图往子视图 倒序遍历查找最适合的responder

1.首先判断 自己是否能接受触摸事件

2.判断触摸点是否在自己身上

3.子控件数组中从后往前遍历子控件,重复前面的两个步骤(所谓从后往前遍历子控件,就是首先查找子控件数组中最后一个元素,然后执行1、2步骤)

4.view,比如叫做fitView,那么会把这个事件交给这个fitView,再遍历这个fitView的子控件,直至没有更合适的view为止。

5.如果没有符合条件的子控件,那么就认为自己最合适处理这个事件,也就是自己是最合适的view。


其中以下三种情况则会阻断查找,自己和自己的所有子视图都不会是那个合适的responder

1.userInteractionEnabled = NO 

2.alpha < 0.01 

3.hidden = YES

// 什么时候调用:只要事件一传递给一个控件,那么这个控件就会调用自己的这个方法// 作用:寻找并返回最合适的view// UIApplication -> [UIWindow hitTest:withEvent:]寻找最合适的view告诉系统// point:当前手指触摸的点// point:是方法调用者坐标系上的点


- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event{
// 1.判断下窗口能否接收事件
if(self.userInteractionEnabled ==NO||self.hidden ==YES||self.alpha <=0.01) return nil;
// 2.判断下点在不在窗口上// 不在窗口上
if([selfpointInside:point withEvent:event] ==NO) return nil;
// 3.从后往前遍历子控件数组
intcount = (int)self.subviews.count;for(inti = count -1; i >=0; i--)    {
// 获取子控件
UIView*childView =self.subviews[i];
// 坐标系的转换,把窗口上的点转换为子控件上的点
// 把自己控件上的点转换成子控件上的点
CGPointchildP = [selfconvertPoint:point toView:childView];

UIView*fitView = [childView hitTest:childP withEvent:event];
if(fitView) {
// 如果能找到最合适的view

return fitView;   

 }   
 }
// 4.没有找到更合适的view,也就是没有比自己更合适的view
return self;   
}

// 作用:判断下传入过来的点在不在方法调用者的坐标系上// point:是方法调用者坐标系上的点
//- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
//{
// return NO;
//}

触摸事件

二 事件响应过程

当找到这个最合适的视图,看它是否重写了touchBegan等方法或者有 UIGesture等手势。先执行重写的touchBegan方法 ( 滑动 - moved方法), 若有手势再执行手势的action,最后执行 touchCancled方法。终止。
 如果都没有,就调用默认实现 super touchXXX 将事件交给上一个响应者。

注意VC.view 根视图的上一个响应者是 VC


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event

{//调用super 就是将事件沿着响应者链条往上传递

[super touchesBegan:touches withEvent: event];

}

事件响应链

两个关键的方法能做什么用


(1).在自定义的父类中写 如下代码 可以在这个父类View  frame 内所有的触摸事件执行前 先执行xxxx ,并且不打断 子控件 的交互


- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event{

    [self xxxx];

    [super  hitTest:point withEvent:event ];

}

(2).touch等方法中先执行xxx,然后再将事件传递给 上一个响应者 如果上一个响应者即写了 touchBegan 又加了手势, 那么会再执行完上一个响应者的touchBegan后,执行手势的action,然后执行上一个响应者的 touchCancled,再执行自己的touchCancled

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event

{

   [self xxx];

    [supertouchesBegan:toucheswithEvent:event];

}

未完待续: 手势理解明天再写。

上一篇下一篇

猜你喜欢

热点阅读