iOS响应者链

本文深入解析iOS中UIResponder的触控事件响应机制,包括响应者对象的概念、响应者链的工作原理,以及事件的产生、传递过程。通过具体实例说明如何通过hitTest和pointInside方法确定事件的最佳响应视图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

响应者对象

继承自UIResponder的对象称之为响应者对象。UIApplication、UIWindow、UIViewController和所有继承UIView的UIKit类都直接或间接的继承自UIResponder。UIResponder一般响应以下几种事件:触摸事件(Touch Event)、运动事件(Motion Event)和远程控制事件(Remote-Control Event)。

响应者链

由多个响应者组合起来的链条,就叫做响应者链。它表示了每个响应者之间的联系,并且可以使得一个事件可选择多个对象处理。

事件的产生和传递

1、当你点击了屏幕产生了一个触摸事件,运行循环(Runloop)会将触摸事件放到UIApplication管理的任务队列中。

2、UIApplication将处于任务队列最前面的事件向下分发。通常先发送事件给UIWindow。

3、UIWindow会在视图层次结构中找到一个最合适的视图来处理触摸事件。

如何找到事件的响应者?

// 此方法返回的View是本次点击事件需要的最佳View
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;

// 判断一个点是否落在范围内
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;
  • 寻找事件的最佳响应视图是通过对视图调用hitTest和pointInside完成的 
  • hitTest的调用顺序是从UIWindow开始,对视图的每个子视图依次调用,子视图的调用顺序是从后面往前面,也可以说是从显示最上面到最下面
  • 遍历直到找到响应视图,然后逐级返回最终到UIWindow返回此视图 

实例

[ViewA addSubview:ViewB];
[ViewA addSubview:ViewC];
[ViewB addSubview:ViewD];
[ViewB addSubview:ViewE];

点击了viewE

1.A 是UIWindow的根视图,首先对A进行hitTest:withEvent:

2.判断A的userInteractionEnabled,如果为NO,A的hitTest:withEvent返回nil;

3.pointInside:withEvent:方法判断用户点击是否在A的范围内,显然返回YES

4.遍历A的子视图B和C,由于从后向前遍历,因此先查看C,调用C的hitTest:withEvent方法:pointInside:withEvent:方法判断用户点击是否在C的范围内,不在返回NO,C对应的hitTest:withEvent: 方法return nil;再查看B,调用B的hitTest:withEvent方法:pointInside:withEvent:判断用户点击是否在B的返回内,在返回YES

5.遍历B的子视图D和E,从后向前遍历,先查看E,调用E的hitTest:withEvent方法:pointInside:withEvent:方法 判断用户点击是否在E的范围内,在返回YES,E没有子视图,因此E对应的hitTest:withEvent方法返回E,再往前回溯,就是B的hitTest:withEvent方法返回E,因此A的hitTest:withEvent方法返回E。

至此,点击事件的第一响应者就找到了。

如果hitTest:withEvent: 找到的第一响应者view没有处理该事件,那么事件会沿着响应者链向上传递->父视图->视图控制器,如果传递到最顶级视图还没处理事件,那么就传递给UIWindow处理,若window对象也不处理->交给UIApplication处理,如果UIApplication对象还不处理,就丢弃该事件。

注意:控件不能响应的情况

  1. userInteractionEnabled = NO
  2. hidden = YES
  3. 透明度 alpha 小于等于0.01
  4. 子视图超出了父视图区域
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值