事件的响应(UIResponder)、touch、UIGestureRecognizer

ios 中事件的处理接口或者说协议是由UIResponder 定义的。

最主要的事件就是touch事件,touch事件是 UIAapplacation 对象 runloop 检测到并封装的。UIApplaction 对象封装好后将事件传递给UIWindeow对象。touch 事件的处理分为两步,第一个步是找到 该touch 所对应的 view,即touch 是那个在那个view上的;第二是步是找到处理该该事件的对象。

第一步的实现,直接调用 UIWindow的

none

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;

方法,该方法 会返回 以调用者为 根的view 树 中touch 事件 所对应的view。该方法的实现是调用所有子view的

none

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;

然后返回 yes 的 子 view 调用

none

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;

这样递归调用直到不存在 叶子 view ,然后返回该View。需要注意的这个递归调用每次传递的 point 值实景过转换的。实在 相应view坐标系下的position。

需要说明的是 view 的UIinterfaceEnable 和 存在 gesture recognize 的 会影像这个过程的进行。 UIinterfaceEnable 为no 的 ,gesture recognize  的 canceltouchinview 为yes 的 则该 过程不会 进行下去。UIinterfaceEnable 为no 的  则 super view 不会 hittest 这样的子view。gesture recognize  的 canceltouchinview 为yes 的 view 不会 hittest 子view。

第二步是找到处理该事件的对象。从第一步找到的View开始 沿着 reponder chain 将 事件传递下去。需要注意的是responder chain 中某一个对象可以 不将 事件 继续往下传,那么 responder chain 下面的对象就不会处理该对象。常见的 chain 是 view –> viewController –>super view –> superview controller —> super super view —> supersuperview controller 最后到rootcontroller 然后到window。需要注意的是  viewcontroller的下一个 responder 是 superview。ios 如果view congroller 的使用不是 按照tabbar navigationbar viewcongroller的方法来使用,就可能产生 responder chain 不对的情况。 (直接将view congroller 的 view addsubiew 到其他view 上)

从上面我们可以看出 一个事件 可以让多个对象同时 知道 并进行处理。这个chain 的实现 的接口就是

none

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

该四个方法的默认实现是调用 nextresponder 的该四个方法。也就是说如果不复写这几个方法,则事件会最终传递到 window,window 的处理一般是直接丢弃。

下面来说说UIGestureRecognizer:

UIGestureRecognizer 对象是添加到 view 对象上面的,当view 收到 hittest 时候,该GestureRecognizer 会被通知到。GestureRecognizer 也是 有并封装了 上面四种方法,然后根据 touch 事件的时间 位置 特征 来 进行 特定的动作。ios系统中提供了 一些UIGestureRecognizer 的子类,这些子类就是处理特定的 touch 序列的。

UIGestureRecognizer 提供了一些代理来 方便的封装了 对上面四种 方法的实现进行 配置。如下面的方法 定义了 是否 根据情况 将 touch 事件 加入到事件序列中,生成响应的动作。

none

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;

除了touch 事件的 其他事件的 处理 需要引入 第一响应者,这些事件包括

none

程序中只有一个第一响应者。第一响应者 相关的 函数是

none

- (BOOL)canBecomeFirstResponder;    // default is NO

- (BOOL)becomeFirstResponder;

- (BOOL)canResignFirstResponder;    // default is YES

- (BOOL)resignFirstResponder;

- (BOOL)isFirstResponder;

对象通过 – (BOOL)becomeFirstResponder; 来向程序 将自己(或者别的对象)注册成第一响应者。被注册者通过- (BOOL)canBecomeFirstResponder;方法来表示自己是不是原因 成为第一响应者。    需要第一响应者的事件到来后,事件会交给第一响应者,然后第一响应者沿着 responder chain 将事件传递下去。motion 事件的 responder chain 是由

none

方法来实现的,该方法 同 touch responder chain 的方法 实现相同,如果没有对象处理,则传递给 UIApplication 对象,然后丢弃。

(转自:http://dcm19872007.blog.163.com/blog/static/865193742013018112558478/)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值