ios 修改父视图子视图_iOS响应链机制

dc2c6a244d9fccb849d16b4019135ca3.png

概述

当我们点击屏幕之后到应用触发响应,这个过程中发生了什么?如何理解iOS的响应链机制,我们可以通过这个机制实现那些功能?本文将着重讲解iOS响应链机制。

点击屏幕到应用捕获事件

f772058742543dee8e12b074fa95271e.png

点击屏幕后,经过系统的一系列处理,我们的应用接收到source0事件,并从事件队列中取出事件对象,开始寻找真正响应事件的视图。

响应者寻找过程分析

寻找相应过程主要涉及到两个方法:

//判断点击的位置是不是在视图内
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;
//返回点击的视图
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;

我们构造了一个简单的视图层级,BlueView/YellowView是两个根节点视图,RedView是他们的父视图。效果如下:

b0d3436f80ac03fed2946ea5c3a961ff.png

我们点击一下BlueView,其事件传递效果如下图:

bc0937bafcc622a2be63e0be68d0b897.png

我们分析一下事件的传递机制。

88800f182388b47aa707364f4514f5cc.png

如果到第4步先找的不是YellowView而是BlueView,则不会再去检查YellowView。

找到最终点击的视图之后开始执行响应逻辑。

事件响应过程

我们点击一下BuleView。

如果BuleView没有添加手势事件,则回调用BlueView的touches事件。

输入的日志:

2020-04-25 17:06:48.992130+0800 ResponderDemo[99230:899392] -[BlueView touchesBegan:withEvent:] 2020-04-25 17:06:48.996208+0800 ResponderDemo[99230:899392] -[BlueView touchesEnded:withEvent:]

如果BuleView也没有实现touches事件,那么则会调用父视图的touches事件。

输出日志如下:

2020-04-25 17:12:10.550668+0800 ResponderDemo[99522:904959] -[RedView touchesBegan:withEvent:] 2020-04-25 17:12:10.555622+0800 ResponderDemo[99522:904959] -[RedView touchesEnded:withEvent:]

如何获取响应链

UIResponder *nextResponder = self.buleView.nextResponder;
NSMutableString *pre = [NSMutableString stringWithString:@"--"];
NSLog(@"View3");
while (nextResponder) {
  NSLog(@"%@%@", pre, NSStringFromClass([nextResponder class]));
  [pre appendString:@"--"];
  nextResponder = nextResponder.nextResponder;
}
  • 如果有父视图则nextResponder指向父视图
  • 如果是控制器根视图则指向控制器
    • 控制器如果在导航控制器中则指向导航控制器的相关显示视图最后指向导航控制器
    • 如果是根控制器则指向UIWindow
  • UIWindow的nexResponder指向UIApplication最后指向AppDelegate。

实践

  1. Alpha=0、子视图超出父视图的情况、userInteractionEnabled=NO、hidden=YES 视图会被忽略,不会调用hitTest
  2. 父视图被忽略后其所有子视图也会被忽略

点击穿透

平行视图:重新hitTest,返回想要点击的View

父子视图: 如果子视图是Button 将button的enable改为false。如果是view不要添加手势即可。

限定点击区域

  • 判定点是不是在可视坐标内。 pointInside
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值