美文网首页IOS Other
iOS事件传递链与响应链

iOS事件传递链与响应链

作者: Ice_Maple | 来源:发表于2023-05-03 10:15 被阅读0次

    1、事件链

    如下图所示,用户点击屏幕时,首先UIApplication对象先收到该点击事件,再依次传递给它上面的所有子view,直到传递到最上层,即UIApplication ——> UIWindow ——> RootViewController ——> View ——> Button,即传递链。

    而反之Button ——> View ——> RootViewController ——> UIWindow ——> UIApplication则称为响应链。

    简单总结,事件链包含传递链和响应链,事件通过传递链传递上去,通过响应链找到相应的UIResponse。

    2、传递链

    由系统向离用户最近的view传递,如上图所示。具体流程如下:

    1、用户在点击屏幕。

    2、系统将点击事件加入到UIApplication管理的消息队列中。

    3、UIApplication会从消息队列中取出该事件传递给UIWindow对象;

    4、在UIWindow中调用方法hitTest:withEvent:返回最终相应的view;

    1、在hitTest:withEvent:方法中调用pointInside:withEvent:来判断当前点击的点是否在UIWindow内部;

    2、如若返回yes,则倒序遍历其子视图找到最终响应的子view;

    3、如果最终返回一个view,那么即为最终响应view并结束事件传递,如果无值返回则将UIWindow作为响应者。见下图:

    其中核心方法如下:

    // recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system

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

    // default returns YES if point is in bounds

    - (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event; 

    1

    2

    3

    4

    方法hitTest:withEvent:用来获取最终响应事件的view。

    方法pointInside:withEvent:,用来判断点击的位置是否在视图范围内。

    以下为UIView不接受事件处理的情况:

    view.hidden = YES;

    view.userInteractionEnabled = NO;

    view.alpha < 0.01;

    1

    2

    3

    3、响应链

    由离用户最近的view向系统传递。如下所示:

    响应链处理具体流程:

    1、若view的 viewcontroller 存在,则将该事件传递给其viewcontroller响应;如若不存在,则传递给其父视图;

    2、若view的最顶层不能处理事件,则传递给UIWindow进行处理;

    3、若UIWindow不能处理,则传递给UIApplication;

    4、若UIApplication不能处理,则将该事件丢弃。

    4、示例代码

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

        UIView *touchView = self;

        // 1、判断 self 是否可以接受事件处理

        // 2、判断 self 是否在点击区间

        if (self.hidden == NO

            && self.alpha >= 0.01

            && [self pointInside:point withEvent:event]) {

            // 3、便利所有子view

            for (UIView *subView in self.subviews) {

                // 4、获取点击的点在子view上的坐标

                CGPoint subPoint = [subView convertPoint:point fromView:self];

                // 5、递归获取点击响应的子view

                UIView *subTouchView = [subView hitTest:subPoint withEvent:event];

                if (subTouchView) {

                    touchView = subTouchView;

                    break;;

                }

            }

        } else {

            // 不接受事件处理直接返回 nil;

            touchView = nil;

        }

        return touchView;

    }

    原文链接:https://blog.csdn.net/weixin_38633659/article/details/125030427

    相关文章

      网友评论

        本文标题:iOS事件传递链与响应链

        本文链接:https://www.haomeiwen.com/subject/xkazjdtx.html