iOS 事件响应

事件响应


入门阶段,你只要学会 Target-Action 即可,基本能满足简单的交互要求 

  • 如果使用 Xib/Storyboard,直接拖拽添加 IBAction 方法即可
  • 如果纯代码,那么需要调用控件的 addTarget:action:forControlEvents: 方法

这两种方式是等价的,与前端 addEventListenter 的方式也很类似

不过你会发现,很多控件是没有 addTarget:action:forControlEvents: 方法的(比如 UIImageView),因为这个方法源自 UIControl,真正的继承结构其实是这样的: UIButton < UIControl < UIView

那如何为 UIImageView 之类的控件添加触摸事件呢?可以使用 UIGestureRecognizer,请看最常用的 UITapGestureRecognizer 子类

UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imgTapped:)]; 
[imgView addGestureRecognizer:tapRecognizer];
imgView.userInteractionEnabled = YES;  // 对于 UIImageView 默认是 NO

可以从 UIGestureRecognizer 的文档中发现更多的子类,涵盖了各种常见手势,比如 Tap/Pinch/Swipe 等等。相比于前端还需要自己通过组合 TouchUp/TouchMove 之类的原始事件来实现手势,iOS 显得方便的多。

学会以上两种方式就能解决很多问题了,不过内在的原理是怎样的呢?有没有类似事件冒泡的机制呢?UITapGestureRecognizer 与 UIControlEventTouchUpInside 有没有关系呢?

想要搞懂这些问题,我推荐仔细阅读这几篇文档: Event Delivery: The Responder Chain , Gesture Recognizers

下面我对原理的简单总结:

  1. 用户触摸开始/移动/结束,都会产生 UITouch 事件
  2. 系统会首先寻找事件对应的 UIView,方法是从外向里通过 hit-test 链(类似捕获)寻找 
  3. 找到对应的 UIView 之后,会根据事件的阶段调用相应方法,如 touchesBegan:withEvent:,方法内如果调用了 super,那么系统会寻找 nextResponder,通常是父 View 或者其对应的 ViewController,再调用相应的 touches 处理方法,这就是从内向外的 Responder 链 (类似冒泡) 
  4. 如果 UIView 没有调用 super,那么事件不再继续传递(类似 stopPropagation)
  5. UIGestureRecognizer 与 UIControl 实际上是对上述机制的更高级封装(手势事件),例如从 UIControlEventTouchUpInside 的名字就可以大概推测出,他其实通过组合 TouchBegin 和 TouchEnd 来封装出的事件(像不像 Zepto 里的 tap 事件封装?不过 iOS 这是内置的)
  6. 为 UIView 添加了 UIGestureRecognizer 之后,UITouch 事件会交给 UIGestureRecognizer,而不再交给 UIView,因此添加了 UITapGestureRecognizer 之后,UIButton 的 UIControlEventTouchUpInside 就不会触发了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值