iOS事件传递链与响应链

简介: iOS事件传递链与响应链

1、事件链


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

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

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



0f4f71a058954c6abdcde0f6ab62e5f4.png

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作为响应者。见下图:

b36f18bd0204d7189e417539943cfb5.png

其中核心方法如下:


// 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;   


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

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

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


view.hidden = YES;
view.userInteractionEnabled = NO;
view.alpha < 0.01;

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/songzhuo1991/article/details/122667980



相关文章
|
Swift iOS开发 开发者
iOS - 跳转App Store下载 app 的两种方式
iOS - 跳转App Store下载 app 的两种方式
2830 0
iOS - 跳转App Store下载 app 的两种方式
|
10月前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
486 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
存储 定位技术 Swift
Swift 中的枚举与结构体,包括它们的定义、特性、使用场景及示例
本文深入探讨了 Swift 中的枚举与结构体,包括它们的定义、特性、使用场景及示例。枚举适合表示有限的、离散的状态或选项,结构体则适用于具有特定属性和行为的数据结构。两者在存储方式、继承性和灵活性上有所不同,但在实际开发中常结合使用,以充分发挥各自优势。
298 3
|
JSON 测试技术 数据格式
Playwright 测试报告器
Playwright 测试报告器
449 4
|
JavaScript
WKWebView采用HybridNSURLProtocol协议拦截图片等资源预加载
WKWebView采用HybridNSURLProtocol协议拦截图片等资源预加载
286 1
|
弹性计算 Kubernetes 容器
k8s基于flannel VXLAN模式网络无法跨主机ping通其他节点上pod
基于云ECS搭建的k8s,通常网络问题需要从网络配置,路由表、iptables 规则 以及FDB配置去判断问题,另外需要注意的是阿里云有一层企业安全组配置会对网络有影响,遇到配置问题都正常需要从安全组的角度去考虑了
8381 0
k8s基于flannel VXLAN模式网络无法跨主机ping通其他节点上pod
|
前端开发 JavaScript API
拥抱华为,困难重重,第一天学习 arkUI,踩坑踩了一天
拥抱华为,困难重重,第一天学习 arkUI,踩坑踩了一天
446 0
|
iOS开发 开发者
iOS响应链
iOS响应链
266 0
iOS响应链
下一篇
oss云网关配置