iOS基础之响应者链

目录 

前言

可用来:
  1. 扩大按钮的点击区域
  2. 
用户操作设备的方式:触摸屏幕、晃动设备、通过遥控设施控制设备。对应的事件类型有以下三种:
    触屏事件(Touch Event)
    运动事件(Motion Event)
    远端控制事件(Remote-Control Event)
  1. 响应者链(即响应链)

由当前响应者向父响应者以上所延伸出的一条链(view->superView…->VC->Window->Appliction)
1、响应者(有响应和处理事件能力的对象)直接或间接继承自UIResponder
2、第一响应者:最先响应事件的响应者
3、当前响应者:当前负责响应事件的响应者

  1. 触摸操作的响应处理过程

1、寻找第一响应者

当iOS系统检测到触摸操作时,会将触摸事件打包成UIEvent对象并存入当前UIApplication应用的事件队列中。UIApplication将触摸事件从事件队列取出,并传递给UIWindow。

UIWindow会调用根视图的hitTest:withEvent:方法,该方法内部会调用pointInside:withEvent:判断触摸点是否在根视图内;
    若不在,则hitTest:withEvent:返回nil; 
    若在,则向当前视图的所有子视图(subviews,index越大越先被访问,所有子视图的遍历顺序是从最顶层视图一直到到最底层视图,即从subviews数组的末尾向前遍历)发送hitTest:withEvent:消息。若子视图还有子辈视图且触摸点在该子视图(当前视图)内则重复上步操作。直到有出现以下2种临界情况,则找到第一响应者,处理结束。
/*
直到2种临界情况
        1、子视图(且该子视图没有子辈视图)的pointInside:withEvent:方法返回true,hitTest:withEvent:方法返回此对象,处理结束。
        2、子视图(且该子视图所有子辈视图pointInside:withEvent:方法返回false即hitTest:withEvent:返回nil)的pointInside:withEvent:方法返回true,则hitTest:withEvent:方法返回此对象,处理结束。
*/

2、向上分发

当前响应者可以选择处理或者忽略响应。选择忽略则交给父节点去响应,选择处理则可选择是否向父节点传递事件(默认:停止分发) 。如果最后交给UIApplication也没处理该事件,则忽略该事件。

例子:如果一个View是UIScrollView的子View,触摸view上下滑动会使UIScrollView滚动。如果一个View只是在UIScrollView的上方,并不是UIScrollView的子View,则触摸view上下并不会使UIScrollView滚动。

返回下一个响应者(即父响应者)

[button nextResponder]

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    UIView *touchView = self;
    if ([self pointInside:point withEvent:event] &&
       (!self.hidden) &&
       self.userInteractionEnabled &&
       (self.alpha >= 0.01f)) {

        for (UIView *subView in self.subviews) {
            [subview convertPoint:point fromView:self];
            UIView *subTouchView = [subView hitTest:subPoint withEvent:event];
            if (subTouchView) {
                touchView = subTouchView;
                break;
            }
        }
    } else {
        touchView = nil;
    }

    return touchView;
}
  1. hitTest:withEvent:会忽略哪些视图

1、隐藏(hidden=YES)的视图
2、禁止用户操作(userInteractionEnabled=false、或 enable=false)的视图
3、以及alpha级别小于0.01(alpha<0.01)的视图
4、子视图超过父视图的区域

  1. hitTest:withEvent:的应用

1. 扩大按钮的点击范围
2. 重叠时希望下方View响应事件

示例1: 扩大按钮的点击范围

继承:ZYDMatchPraiseButton即可

@interface ZYDMatchPraiseButton : UIButton
@end
@implementation ZYDMatchPraiseButton
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
    CGRect rect=self.bounds;
    CGFloat width=rect.size.width;
    CGFloat height=rect.size.height;
    rect=CGRectInset(rect, -width*0.5, -height*0.5);  // 宽高各扩大了一半
    return CGRectContainsPoint(rect, point);
}
/*
// 另一种,按固定大小
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event {
    return CGRectContainsPoint(HitTestingBounds(self.bounds, 100, 100), point);
}
CGRect HitTestingBounds(CGRect bounds, CGFloat minimumHitTestWidth, CGFloat minimumHitTestHeight) {
    
    //
    CGRect hitTestingBounds = bounds;
    if (minimumHitTestWidth > bounds.size.width) {
        hitTestingBounds.size.width = minimumHitTestWidth;
        hitTestingBounds.origin.x -= (minimumHitTestWidth - bounds.size.width)/2;
    }
    if (minimumHitTestHeight > bounds.size.height) {
        hitTestingBounds.size.height = minimumHitTestHeight;
        hitTestingBounds.origin.y -= (minimumHitTestHeight - bounds.size.height)/2;
    }
    return hitTestingBounds;
}
*/
@end
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352