专栏首页ios 技术积累iOS 事件传递与视图响应链

iOS 事件传递与视图响应链

当你点击了屏幕上的某个view,这个动作由硬件层传导到操作系统,UIKit 就会打包出一个 UIEvent 对象,然后会把这个Event分发给当前正在活跃的 App ,告知当前活动的App有事件之后,UIApplication 单例就会从事件队列中去取最新的事件,然后分发给能够处理该事件的对象。UIApplication 获取到Event之后,Application就纠结于到底要把这个事件传递给那个View来响应这个事件,这时候就要依靠HitTest来决定了。

iOS中,Hit-Test的作用就是找出这个触摸点下面的View是什么,HitTest会检测这个点击的点是不是发生在这个View上,如果是的话,就会去遍历这个View的subviews,直到找到最小的能够处理事件的view,如果整了一圈没找到能够处理的view,则返回自身然后从sub View 又开始找。

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

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;
逻辑流程图
具体实现
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    // 1.判断当前控件能否接收事件
    if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) {return nil;}
    
    // 2. 判断点在不在当前控件
    if ([self pointInside:point withEvent:event] == NO) {return nil;}

    // 3.从后往前遍历自己的子控件
    NSInteger subViewCoutn = self.subviews.count;

    for (NSInteger i = subViewCoutn - 1; i >= 0; i--) {
        // 取subView
        UIView *childView = self.subviews[i];
        // 把当前控件上的坐标系转换成子控件上的坐标系
        CGPoint childP = [self convertPoint:point toView:childView];
        // 寻找到最合适的view
        UIView *fitView = [childView hitTest:childP withEvent:event];
        
        if (fitView) {
            return fitView;
        }
    }
    
    NSLog(@"点击了:%@",NSStringFromClass([self class]));

    // 循环结束,表示没有比自己更合适的view
    return self;
    
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • iOS中的事件的产生和传递

    ●发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中,为什么是队列而不是栈?因为队列的特点是FIFO,即先进先出,先产生的事件...

    赵哥窟
  • ios Charts MarkerView遇到的一个问题

    两个问题 问题1:最大值的的时候 MarkerView 坐标有问题 ,原因就是最大值的时候,曲线已经在View的顶部了,所以MarkerView 的Y坐标还要...

    赵哥窟
  • iOS UITableView 无数据占位图

    在使用TableView的时候,经常会遇到一些无数据需要用到占位图的情况,所以就写一个控件来实现。 思路:使用UITableView Category来实现,...

    赵哥窟
  • Python %r和%s区别代码实例解析

    砸漏
  • 【LeetCode题解---2】Add Two Numbers

    You are given two non-empty linked lists representing two non-negative integers....

    周三不加班
  • 什么是SAP S/4HANA的extension flow

    Suppose I have extended MARA with the following field, how could I know whether ...

    Jerry Wang
  • echart图表切换tab不显示的解决方法 原

    tianyawhl
  • LeetCode之Add Two Numbers

      先分位求总和得到 totalsum,然后再将totalsum按位拆分转成链表;

    Christal_R
  • [Leetcode][python]Add Two Numbers/两数相加

    给定两个链表分别代表两个非负整数。数位以倒序存储,并且每一个节点包含一位数字。将两个数字相加并以链表形式返回。

    后端技术漫谈
  • 无人驾驶汽车系统入门:基于VoxelNet的激光雷达点云车辆检测及ROS实现

    之前我们提到使用SqueezeSeg进行了三维点云的分割,由于采用的是SqueezeNet作为特征提取网络,该方法的处理速度相当迅速(在单GPU加速的情况下可达...

    AI科技大本营

扫码关注云+社区

领取腾讯云代金券