事件分发与响应者链

在iOS中事件分为三类:

  1. 触摸事件:通过触摸、手势进行触发(点击,缩放等)
  2. 运动事件:通过加速器进行触发(微信摇一摇等)
  3. 远程控制事件:通过其他远程设备触发(线控耳机)

只有继承自UIResponder的类才能处理事件

下面说一下触摸事件

当用户触摸屏幕时,事件会被封装成一个event实例,包含了触摸相关信息,然后操作系统对其进行分发,由响应者类进行处理(UIResponder的子类);

简单的分发与响应过程图:

1.事件的分发

iOS系统检测到手指触摸(Touch)操作时会将其放入当前活动Application的事件队列,UIApplication会从事件队列中取出触摸事件并传递给key window(当前接收用户事件的窗口)处理,window对象首先会使用hitTest:withEvent:方法寻找此次Touch操作初始点所在的视图(View),即需要将触摸事件传递给其处理的视图,称之为hit-test view。

window对象会在首先在view hierarchy的顶级view上调用hitTest:withEvent:,此方法会在视图层级结构中的每个视图上调用pointInside:withEvent:,如果pointInside:withEvent:返回YES,则继续逐级调用,直到找到touch操作发生的位置,这个视图也就是hit-test view。

hitTest:withEvent:方法的处理流程如下:

  1. 首先调用当前视图的pointInside:withEvent:方法判断触摸点是否在当前视图内;
  2. 若返回NO,则hitTest:withEvent:返回nil;
  3. 若返回YES,则向当前视图的所有子视图(subviews)发送hitTest:withEvent:消息,所有子视图的遍历顺序是从top到bottom,即从subviews数组的末尾向前遍历,直到有子视图返回非空对象或者全部子视图遍历完毕;
  4. 若第一次有子视图返回非空对象,则hitTest:withEvent:方法返回此对象,处理结束;
  5. 如所有子视图都返回非,则hitTest:withEvent:方法返回自身(self)

简单来说,通过hitTest:withEvent:pointInside:withEvent:这两个方法找到触摸对象(触摸对象并不一定就是响应者)

2.响应者链

简单来说响应者链就是一些拥有当前事件处理权力的实例对象组成的链条(如理解有误请指出)

响应者链上的对象   1.处理事件(处理事件之后事件将不继续向下一响应者传递,可以通过复写方法把当前事件交给某一对象进行处理)

          2.不处理(如果所有响应者都不处理事件,最终事件被丢弃)

可以复写下列方法对事件进行处理

//触摸开始,手指触碰屏幕
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
//触摸结束,手指离开屏幕
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
//触摸取消(如电话接入的时候)
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
//手指移动(会调用多次)
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
//3D touch 9.1之后加入的3D触摸事件
- (void)touchesEstimatedPropertiesUpdated:(NSSet *)touches

 需要注意的是:UIView有几种情况者不能处理事件

  1.userInteractionEnabled=NO (UIImageView的userInteractionEnabled 默认就是NO)

  2.hidden=YES

  3.alpha小于0.01

3.开发过程中也会碰到这样的需求:

例如触摸一个UIView实例对象,要将页面进行跳转,一般这个功能是由视图(UIViewController)控制器来完成的,

这样我们就需要找到当前视图的视图控制器对事件进行处理,方法如下

- (UIViewController *)viewController
{
    UIResponder *responder = self.nextResponder;
    do {
        if([responder isKindOfClass:[UIViewController class]])
        {
            return (UIViewController *)responder;
        }
        responder = responder.nextResponder;

    }while (responder != nil);

    return nil;
}

需要其他对象对事件进行处理方法类似(只要这个对象在响应者链上)

时间: 2024-11-07 04:15:19

事件分发与响应者链的相关文章

iOS学习9_事件分发&amp;amp;响应链

iOS的三种事件:触摸事件/运动事件/远程控制事件 typedef enum { UIEventTypeTouches, UIEventTypeMotion, UIEventTypeRemoteControl, } UIEventType; 仅仅有继承UIResponder类的对象才干处理事件,如UIView.UIViewController.UIApplication都继承自UIResponder,都能接收并处理事件.UIResponder中定义了上面三类事件相关的处理方法: 以下主要讨论触摸

iOS中的事件传递和响应者链

首先我们来看看iOS中事件的产生和传递过程: 1.发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的队列事件中 2.UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常会先发送事件给应用程序的主窗口(keyWindow) 3.主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件 4.找到合适的视图控件后,就会调用视图控件的touches方法来作事件的具体处理:touchesBegin... touchesMoved...touch

《从零开始学Swift》学习笔记(Day 68)——Cocoa Touch设计模式及应用之响应者链与触摸事件

原创文章,欢迎转载.转载请注明:关东升的博客 应用与用户进行交互,依赖于各种各样的事件.事件响应者对象是可以响应事件并对其进行处理的对象,响应者链是由一系列链接在一起的响应者组成的.响应者链在事件处理中是非常重要的,响应者链可以把用户事件路由给正确的对象. 响应者对象与响应链 UIResponder是所有响应者对象的基类,它不仅为事件处理,而且也为常见的响应者行为定义编程接口.UIApplication.UIView(及其子类,包括UIWindow)和UIViewController(及其子类)

iOS响应者链

首先,当发生事件响应时,必须知道由谁来响应事件.在IOS中,由响应者链来对事件进行响应,所有事件响应的类都是UIResponder的子类,响应者链是一个由不同对象组成的层次结构,其中的每个对象将依次获得响应事件消息的机会.当发生事件时,事件首先被发送给第一响应者,第一响应者往往是事件发生的视图,也就是用户触摸屏幕的地方.事件将沿着响应者链一直向下传递,直到被接受并做出处理.一般来说,第一响应者是个视图对象或者其子类对象,当其被触摸后事件被交由它处理,如果它不处理,事件就会被传递给它的视图控制器对

UI-事件,触摸与响应者链(一)

首先,当发生事件响应时,必须知道由谁来响应事件.在IOS中,由响应者链来对事件进行响应,所有事件响应的类都是UIResponder的子类,响应 者链是一个由不同对象组成的层次结构,其中的每个对象将依次获得响应事件消息的机会.当发生事件时,事件首先被发送给第一响应者,第一响应者往往是事件发 生的视图,也就是用户触摸屏幕的地方.事件将沿着响应者链一直向下传递,直到被接受并做出处理.一般来说,第一响应者是个视图对象或者其子类对象,当其被 触摸后事件被交由它处理,如果它不处理,事件就会被传递给它的视图控

响应者和响应者链

核心的应用程序对象-NSApplication.NSWindow.和NSView-都是响应者,它们是NSResponder(参见图6-19)的直接或间接子类的实例.这个抽象类定义了能够响应事件的对象的接口和期望的行为.NSResponder的子类完全或部分实现了这个行为. 图6-19  NSResponder及其直接子类 请注意:还有其它两个Application Kit类直接继承自NSResponder:NSWindowController和NSDrawer.虽然NSWindowControl

响应者链的事件分发

响应者链的事件分发:从Window的视图开始分发向上传(向内部传),一定要分清楚谁是谁的子视图以及同级视图中他们的先后顺序,具体流程请看代码 //分发事件的方法 /* 0.判断该点是否在视图内,如果不是返回nil 1.遍历子视图(倒序) 2.转换坐标系 3.分发给子视图 4.查看触摸点在不在子视图中 在的话子视图调用hitTest,如果有返回值,直接返回,循环结束,方法结束 5.如果没有,返回self */ - (UIView *)hitTest:(CGPoint)point withEvent

iOS事件的分发机制和响应者链(Swift)

当我们在设计自己的APP时,可能会想动态的响应事件.例如:屏幕上许多对象都能够发生触摸,我们必须决定哪一个对象来响应给定的事件并且知道对象是如何接受事件的.当用户事件产生的时候,UIKit会创建一个事件对象(event object),该对象包含了事件整个过程中所拥有的信息.并且该事件对象将处于APP活跃事件列队中.对于触摸事件,对象将包含一系列UIEvent对象.对于运动事件,取决于你使用的框架和你感兴趣的运动事件的类型. 事件沿着具体的路径进行传递,一直到发现对象能够处理该事件,首先,UIA

事件分发&amp;响应链

iOS的三种事件:触摸事件/运动事件/远程控制事件 [objc] view plaincopy typedef enum { UIEventTypeTouches, UIEventTypeMotion, UIEventTypeRemoteControl, } UIEventType; 只有继承UIResponder类的对象才能处理事件,如UIView.UIViewController.UIApplication都继承自UIResponder,都能接收并处理事件.UIResponder中定义了上面