iOS触摸事件传递与响应链

本文通过实例演示了iOS中UI事件如何从顶层视图向子视图传递,并解释了响应链的概念,即当子视图未处理事件时,事件会向上层视图传递。

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

事件的传递过程实际上是寻找最合适响应者过程    

控制器中创建如下三个视图

    RedView *redview = [[RedView alloc] initWithFrame:CGRectMake(0, 0, 300, 400)];

    redview.backgroundColor = [UIColor redColor];

    redview.center = self.view.center;

    [self.view addSubview:redview];

    

    BlueView *blueView = [[BlueView alloc] initWithFrame:CGRectMake(0, 150, 100, 100)];

    blueView.backgroundColor = [UIColor blueColor];

    [redview addSubview:blueView];

    

    Blackview *blackview = [[Blackview alloc] initWithFrame:CGRectMake(200, 150, 100, 100)];

    blackview.backgroundColor = [UIColor blackColor];

    [redview addSubview:blackview];


RedView、BlueView、Blackview中分别实现如下两个方法:


#import "RedView.h"


@implementation RedView


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

{

    NSLog(@"1");

    return [super hitTest:point withEvent:event];

}


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

{

    NSLog(@"我是红的");

}

@end


#import "Blackview.h"


@implementation Blackview

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

{

    return [super pointInside:point withEvent:event];

}


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

{

    NSLog(@"2");

    return [super hitTest:point withEvent:event];

}


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

{

    NSLog(@"我是黑的");

}


#import "BlueView.h"


@implementation BlueView


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

{

    NSLog(@"3");

    return [super hitTest:point withEvent:event];

}


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

{

    NSLog(@"我是蓝的");

}

@end

分别点击红色区域、黑色区域、蓝色区域

Log打印如下:

点击红色:

2018-03-09 14:44:56.293861+0800 事件传递与响应链[1479:108377] 1

2018-03-09 14:44:56.294000+0800 事件传递与响应链[1479:108377] 2

2018-03-09 14:44:56.294207+0800 事件传递与响应链[1479:108377] 3

2018-03-09 14:44:56.294727+0800 事件传递与响应链[1479:108377] 我是红的


点击黑色:


2018-03-09 14:48:04.124764+0800 事件传递与响应链[1479:108377] 1

2018-03-09 14:48:04.124873+0800 事件传递与响应链[1479:108377] 2

2018-03-09 14:48:04.125326+0800 事件传递与响应链[1479:108377] 我是黑的


点击蓝色:

2018-03-09 14:49:05.530768+0800 事件传递与响应链[1524:118234] 1

2018-03-09 14:49:05.530867+0800 事件传递与响应链[1524:118234] 2

2018-03-09 14:49:05.530959+0800 事件传递与响应链[1524:118234] 3

2018-03-09 14:49:05.532497+0800 事件传递与响应链[1524:118234] 我是蓝的

     事件传递流程,从self.view开始往下写

     点击红色: self.view(触摸点在自己身上 从后向前遍历子控件)-redView(触摸点在自己身上 从后向前遍历子控件)- blackView(触摸点不在自己身上)-blueView(触摸点不在自己身上)-redView最合适

     点击黑色: self.view(触摸点在自己身上 从后向前遍历子控件)-redview(触摸点在自己身上 从后向前遍历子控件)- blackView(触摸点在自己身上 从后向前遍历子控件)无子控件,即自身最合适

     点击红色: self.view(触摸点在自己身上 从后向前遍历子控件)-redview(触摸点在自己身上 从后向前遍历子控件)- blackView(触摸点不在自己身上)-blueView(触摸点在自己身上 从后向前遍历子控件)无子控件,即自身最合适


事件传递顺序:总是从父视图向子视图传递,对于这个实验事件传递应该是UIApplication->KeyWindow->self.View->redView->blackView->blueView,对于同一个父视图下的子视图,总是先访问后添加上的子视图。

所以判断是否为最合适响应视图的定义为,触摸点在某个具备响应能力的视图上且其子视图集合a具备下列条件之一:触摸点不在a上、a无响应能力、a集合为空。

响应链:

将BlueView的touchesBegan方法注释掉

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

{

    NSLog(@"我是蓝的");

}

再次点击blueView,log如下:

2018-03-09 15:08:10.169678+0800 事件传递与响应链[1653:128205] 1

2018-03-09 15:08:10.169797+0800 事件传递与响应链[1653:128205] 2

2018-03-09 15:08:10.169890+0800 事件传递与响应链[1653:128205] 3

2018-03-09 15:08:10.171435+0800 事件传递与响应链[1653:128205] 我是红的

说明响应链中是由下向上传递的,当最下层没有响应方法时,信息将向上层(父视图)传递,这里blueView没有实现 touchesBegan方法,所以传向其父视图redView。


更详细介绍请点击 传送门


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值