iOS 事件机制

事件

iOS 将事件分为三类:

  • Touch
  • Motion
  • Remote
    像耳机线控……

Touch 事件

Touch 事件的过程:事件产生 ==》 事件分发 ==》 事件响应

事件产生

iOS每产生一个事件都会生成一个 UIEvent 对象,它记录了事件的类型( UIEventType / UIEventSubtype (主要用在Motion和Remote) )、时间、几个手指触控等信息
当手指触摸屏幕时,每个手指都会产生一个 UITouch 对象,它保存着跟手指相关的信息,如触摸的位置、时间、阶段( UITouchPhase )等
UIEvent 和 UITouch 关系 -- UIEvent 有一方法 - allTouches ,返回 NSSet 集合的一组 UITouch 对象,即一个 UIEvent 包含一个或多个 UITouch 对象

确定点击对象

Hit Test -- iOS 通过 Hit Test 来寻找触摸点下面的 view 是什么

[UIView class]
- hitTest:withEvent:

Hit Test小结:

  • 从 UIWindow 开始,先父 view 后子 view
  • subViews 按照逆顺序遍历
  • 在代码中是嵌套调用


如上图,当我们点击 view4 的区域,有

hit test from view TestWindow
hit test from view 0
hit test from view 2
return hit view (null), self view 2
hit test from view 1
hit test from view 4
return hit view 4, self view 4
return hit view 4, self view 1
return hit view 4, self view 0
return hit view 4, self view TestWindow

事件分发

UIApplication 和 UIWindow 有方法 - sendEvent: ,用于把事件分发到 hitTest View

UIApplication == sendEvent: ==> UIWindow == sendEvent: ==> hitTest View

事件响应

能响应事件的类必须继承于一个类 -- UIResponder,UIApplication / UIViewController / UIView( UI ) / AppDelegate 都继承于 UIResponder
通常来说,我们首先找到的 hitTest View,就是 Touch 事件的第一个 Responder

UIResponder 的响应过程

触摸开始 ==》 触摸移动 ==》 触摸结束 ,还有触摸取消

- touchesBegan:withEvent:
- touchesMoved:withEvent:
- touchesEnded:withEvent:
- touchesCancelled:withEvent:
UIResponder 的响应顺序

响应链 ( Responder Chain ) 即一系列关联的响应对象 ( a series of linked responder objects )
first responder ==> next responder ==> ... ==> UIWindow ==> UIApplication ==> AppDelegate ==> 丢弃
subView/hitTestView ==> superView/VC.view ==> VC ==> VC' superView ==> root VC ==> window ==> application ==> AppDelegate ==> 丢弃

  • 如果想事件继续传递下去,可以调用 [super touchesBegan:touches withEvent:event],不建议直接调 [self.nextResponder touchesBegan:touches withEvent:event]
UIView 不响应事件的条件
  • userInteractionEnabled = NO
  • hidden = YES
  • alpha ( 0-0.01 )

UIView 加大点击区域

假设一个按钮,希望能在其显示区域的一定范围外,也能响应点击事件

  • 最直观的做法:加大透明按钮
  • 事件机制 hitTest
    在父 view 的 - hitTest:withEvent: 方法中,判断如果点击的point 在要求的 rect 中时,直接返回 button ,否则返回 [super hitTest:point withEvent:event] 继续传递
    • pointInside:withEvent:
  • hitTest:withEvent: 方法会递归地调用 - pointInside:withEvent: 方法,- pointInside:withEvent: 用来判断触摸的 point 是否在 view 的范围内
    button 可以重写这一方法
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    CGFloat buttonExtraPadding = 20;

    CGPoint convertPoint = [self convertPoint:point toView:self.superview];
    CGRect targetRect = CGRectInset(self.frame, - buttonExtraPadding, - buttonExtraPadding);
    if (CGRectContainsPoint(targetRect, convertPoint))
    {
        return YES;
    }

    return [super pointInside:point withEvent:event];  
}

子 view 超过父 view 范围

当子 view 超出父 view 的范围时,在父 view 范围内的部分能够响应事件,超出父 view 部分则不能响应事件
因为在 hitTest View 时,父 view 的 hitTest View 监测到不在范围内,因而也不会递归调用到子 view 的 hitTest

// 重写父 view 的 - pointInside:withEvent: 方法,使当确定 point 在子 view 范围内时,返回 YES
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    // point 需要转换到子 view 的坐标系
    if ([_button pointInside:[self convertPoint:point toView:_button] withEvent:event])
    {
        return YES;
    }

    return [super pointInside:point withEvent:event];
}

全局监控 touch 事件

  • UIWindow 子类
    UIWindow 有 - sendEvent: 方法,可以捕获到所有的 Touch 事件
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容