iOS开发攻城狮的集散地iOS面试知识点iOS性能优化

结合一道面试题浅谈触摸事件的流程

2018-10-25  本文已影响6人  dj_rose
题.png
条件:红色View 是蓝色View的子视图、蓝色View是绿色View的子视图
问:点击超出蓝色View的红色View 会有反应吗?如果没有,有什么简单的办法让其响应红色view的事件?

一看到这种问题,大多数人的第一想法就是重写蓝色view的hitTest方法,同时重写蓝色view的pointInside:方法。

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if ([self pointInside:point withEvent:event]) {
        return 红色view;
    }
    return [super hitTest:point withEvent:event];
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    if (坐标在红色view内) {
        return YES;   
    }
    //否则返回默认的操作
    return [super pointInside:point withEvent:event];
}

通过这两个方法配合,将最佳响应者改变为红色view。

群里有大佬就是这么回答的。然而面试官似乎并不满意,又问:有没有更简单的?

有的同学说:改变下view的层级吧,这样最简单~

很显然,面试官又补充了一点:不能改变现有视图层级、不能改变view的大小。

这下就有点懵逼了。。。

记得之前看过一篇触摸事件的文章,讲的很详细--iOS触摸事件全家桶

于是又去翻看了下,边看边思考,面试官问的这个更简单的方法到底是想考察哪一块的知识点?

回顾完那篇文章,简单总结下触摸事件的流程:

系统响应 --> 传递给前台app --> 寻找事件最佳响应者(hit-testing)--> 事件的响应及在响应链中的传递

不难发现,我们上面的hitTest:解决方案是在寻找事件最佳响应者(hit-testing)的过程中去改变了最佳响应者。那么,面试官所说的更简单的方法,是不是在事件最佳响应者确定了之后,事件响应过程中去拦截处理?

答案:是的!

可能是面试官想要的更简单的方案

在寻找事件的最佳响应者的过程中,事件自下而上进行传递。

UIApplication ——> UIWindow ——> 子视图 ——> ... ——> 子视图

最佳响应者确定之后,事件从最佳响应者开始,自上而下的进行事件的响应及传递。
响应者对于事件的拦截以及传递都是通过 touchesBegan:withEvent: 方法控制的,该方法的默认实现是将事件沿着默认的响应链往下传递。

因此我们可以简单的通过重写控制器VC的touchesBegan:方法来拦截红色view的点击事件

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint point = [touch locationInView:_blueView];
    if (CGRectContainsPoint(_redBtn.frame, point)) {
        [self clickTest];
    }
}

写到这里,感叹出题者对于触摸事件的考察点理解的真的是相当透彻,发人深省~

上一篇下一篇

猜你喜欢

热点阅读