美文网首页
响应链 --- 被很多人忽视的另一种数据交互方式

响应链 --- 被很多人忽视的另一种数据交互方式

作者: moxacist | 来源:发表于2018-01-23 13:47 被阅读94次

前言

这篇文章有些是借鉴了其他博客文章的知识点加以理解的,在最下方我会列出参考的链接。有兴趣的可以点进去看下。

主要内容

本篇文章的主要内容有响应链的构成、响应链的传递过程、hit:test判定流程、通过响应链进行交互传递。

1.响应链的构成

从名字中开始理解,响应链是由一系列响应者通过某种联系构成的链条。

  • 响应者:具有响应和处理事件能力的对象。基类是UIResponder=

  • 链条连接器:pointInside 和hit:test方法

  • 响应者类关系图


    响应者类关系图.png

2.响应链的传递

当界面上的一个button被点击时
  • 1.系统会封装一个UIEvent对象传递到Appdelegate
  • 2.由Appdelegate向Application、UIWindow等向上传递事件
  • 3.视图收到父响应者传递的事件后,通过hitView判断是否选中
  • 4.如果没有判定中,那么不处理,如果判定中,遍历子视图,递归执行3和4
  • 5.最后递归找到最顶层的button,最适合的视图
  • 6.如果能响应,执行它的交互响应 ,不能的话,递归到上一个响应者,执行响应 。
  • 7.如果一直递归到appdelegate到都没响应,则废弃

不能响应的原因 :

  • view.hidden = YES
  • view.alpha<0.01
  • view.userinterface = NO
  • 不添加交互事件并不是不能响应,只是默认不做处理
响应链层级 传递图

3.hit:test流程

刚才我们说到响应者需要将事件在响应链上传递,在内部是通过两个方法进行传递 pointinside 和hit test

1.首先对响应链最底层的View(UIWindow)视图进行命中判定,调用hittest:withevent方法
2.如果判定不是该视图,则返回nil,pointInside:withevent方法无效,如果命中,则根据pointInside, 返回是不是响应区域,如果是,则遍历该视图的子视图进行hittest判定
3.重复2,知道找到最上层最合适的视图,然后执行事件

这张图是盗的
假设用户点击了视图E

1.首先touch会命中window,查出上级视图是viewA
2.viewA判定在A中,然后向上遍历子视图B和C
3.B判定不在自己的视图内,返回nil,B分支结束
4.C判定在自己的视图内,向上遍历D和E进行判定
5.D判定不在视图内,D分支结束
6.E判定在该视图内,子视图为nil,则E是最合适视图

  1. E进行响应,如果E无法响应,则执行父视图C的响应

以上就是响应链传递的流程,说完了流程现在来说说响应链具体有何应用

应用一: 超区或者裁区响应
image.png

对于这张图片,一般简单做法就是方形视图切圆角,这样的话圆形周边的四个角(红色区域)也会响应,如果交互或者产品要求只能圆形响应的话,这时候就需要重写方法

#import "EDHSqurView.h"

@implementation EDHSqurView

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    NSLog(@"%s",__func__);
    UIView *vuew = [super hitTest:point withEvent:event];
    return vuew;
}

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
    NSLog(@"%s",__func__);
    //已经知道是个正方形
    CGFloat radius = self.frame.size.width/2;
   
    UIBezierPath *bezier = [UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius)
                                                          radius:radius
                                                      startAngle:0 endAngle:M_PI*2
                                                       clockwise:1];
    return CGPathContainsPoint(bezier.CGPath, NULL, point, NO);
    
}

@end

这段代码要用到的是下面那个方法,进行裁剪交互区域,返回可交互的圆形区域

按钮超区.png

这段图片也是进行超区处理

应用二:通过响应链进行对象间交互
目前常用的数据/事件回传有block、delegate、notification,各有所长。响应链具有逐层传递的特点,可通过nextresponder取到下一个响应者,基于这个特点,可以设计通过链路进行对象的数据回传

具体做法

  • 1.通过UIResponder的一个category,定义一个方法,通过响应链向底层传递
  • 2.通过extern nsstring const 方式定义交互事件的eventname名字(也可以硬编码)
  • 3.以tableview为例,cell上有多个交互事件,在button的点击事件里调用category方法
  • 4.在controller里面接收到上一层响应者发来的信息,处理,若需要继续传递(或穿透传递) 则调用category的方法


    1-定义分类
    2-定义eventname
    3-在交互事件是执行category
    4-在控制器里的操作
下层响应者接受多个响应事件的strategy模式

当下层响应者例如controller接受来自多个子视图的事件时,会导致判断的if else冗余,这时可以采用strategy对每个eventname分类处理

解决办法:定义一个字典,eventname做key,invocation做value
在routeEvent里面通过eventname取出strategy字典的value - invocation,
然后[invocation invoke]

这种方式要求每个eventname都对应一个selector,如果event不是很多的话,
用if else 也没什么关系
如下图


定义event字典 事件调用的地方
  • 响应链传递和代理block等的使用对比
image.png
参考文章
demo链接: https://github.com/MoonMD/ResponderDemo.git

相关文章

  • 响应链 --- 被很多人忽视的另一种数据交互方式

    前言 这篇文章有些是借鉴了其他博客文章的知识点加以理解的,在最下方我会列出参考的链接。有兴趣的可以点进去看下。 主...

  • 基于ResponderChain的事件传递

    ResponderChain对象交互方式本质 响应者链简介 Responder Chain也就是响应链,响应者链是...

  • 响应者链

    1.1 响应者链 当与某控件交互时,该控件将作为"第一响应者 (First Responder)",作为响应者链的...

  • 转载:响应者链工作原理

    响应者链 响应者链是由一个一个响应者组成的长链;响应者链定义了iOS中触摸事件的交互规则;如果hit-test检测...

  • iOS响应者链

    响应者 : 对用户交互动作事件进行响应的对象。 响应者链:成为处理事件的响应者的先后顺序链。 1.Hit-Test...

  • 响应者链及相关机制总结

    概念 响应者 : 对用户交互动作事件进行响应的对象。响应者链:成为处理事件的响应者的先后顺序链。 正文 1、Hit...

  • 微服务间的通信异步交互模式

    异步交互模式 理想情况是所有交互都使用异步交互,但是实际中不太可能。 优化方式 1.复制数据 2.先返回响应,再完成处理

  • UIResponder之事件响应者链

    概念 1.响应者:对用户交互动作事件进行响应的对象。2.响应者链:成为处理事件的响应者的先后顺序的链。 正文 Hi...

  • ios 响应链

    首先清楚两个概念响应者:对用户交互动作事件进行响应的对象。响应者链:成为处理事件的响应者的先后顺序链。平时当我们点...

  • iOS事件的传递链和响应链

    彻底理解事件的传递链和响应链需要先弄明白iOS对象为什么可以响应用户交互,理解UIResponder类; 1.1响...

网友评论

      本文标题:响应链 --- 被很多人忽视的另一种数据交互方式

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