美文网首页
事件传递和响应机制

事件传递和响应机制

作者: 陌巷先森 | 来源:发表于2019-02-28 10:15 被阅读0次

    iOS中的事件

    1.事件的生命周期

    事件的生命周期从事件的产生和传递(事件如何从父控件传递到子控件并寻找到最合适的view、寻找最合适的view的底层实现、拦截事件的处理)->事件的响应(找到最合适的view后对事件进行处理,touches方法的重写)

    2.事件的分类

    iOS中的事件可以分为3大类型:

    • 触屏事件(例如点击按钮、通过手势缩放图片、拖动上下滚动页面等)
    • 传感器事件(例如摇一摇红包、通过旋转设备控制赛车方向、指南针等)
    • 远程控制事件(例如耳机的线控、外接手柄、遥控器等)

    3.响应者对象(UIResponder)

    在iOS中只有继承了UIResponder的对象才能接收和处理事件,UIResponder的子类包括UIView,UIViewController,UIApplication等。响应者接收到原始事件数据,必须处理事件转发到另一个响应者对象,当APP接收到一个事件事,UIKit自动引导事件到最合适的的响应者对象,也叫做第一响应者。
    UIResponder内部提供了以下方法来处理事件

    触摸事件
    - (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;
    加速计事件
    - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;
    - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event;
    - (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event;
    远程控制事件
    - (void)remoteControlReceivedWithEvent:(UIEvent *)event;
    

    4.事件中的概念

    在自定义UIView为属性的控件时可以重写触摸事件的方法来进行点击回调。在回调中可以看到方法接收两个参数,一个是UITouch对象的集合,还有一个是UIEvent对象。

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
        NSLog(@"触摸开始--touches:%@,event:%@",touches,event);
    }
    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
        NSLog(@"开始移动--touches:%@,event:%@",touches,event);
    }
    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
        NSLog(@"触摸结束--touches:%@,event:%@",touches,event);
    }
    //只有在程序强制退出或者来电时才会调用
    - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
        NSLog(@"触摸取消--touches:%@,event:%@",touches,event);
    }
    

    4.1UIEvent

    表示用户交互的事件对象,每产生一个事件,就会产生一个UIEvent对象。在一个用户点击事件处理过程中,UIEvent对象是唯一的。
    UIEvent属性如下:

    //事件类型
    @property(nonatomic,readonly) UIEventType     type NS_AVAILABLE_IOS(3_0);
    @property(nonatomic,readonly) UIEventSubtype  subtype NS_AVAILABLE_IOS(3_0);
    //事件产生时间
    @property(nonatomic,readonly) NSTimeInterval  timestamp;
    

    4.2UITouch

    当用户用一根手指触摸屏幕时,会创建一个与手指相关的UITouch对象 ,一根手指对应一个UITouch对象。
    UITouch属性如下:

    //触摸产生时所处的窗口
    @property(nonatomic,readonly,retain) UIWindow *window;
    //触摸产生时所处的视图
    @property(nonatomic,readonly,retain) UIView *view
    ;
    //短时间内点按屏幕的次数,可以根据tapCount判断单击、双击或更多的点击
    @property(nonatomic,readonly) NSUInteger tapCount;
    //记录了触摸事件产生或变化时的时间,单位是秒
    @property(nonatomic,readonly) NSTimeInterval timestamp;
    //当前触摸事件所处的状态
    @property(nonatomic,readonly) UITouchPhase phase;
    

    UITouch方法如下:

    // 返回值表示触摸在view上的位置
    // 这里返回的位置是针对view的坐标系的(以view的左上角为原点(0, 0))
    // 调用时传入的view参数为nil的话,返回的是触摸点在UIWindow的位置
    (CGPoint)locationInView:(UIView *)view;
    // 该方法记录了前一个触摸点的位置
    (CGPoint)previousLocationInView:(UIView *)view;
    

    事件的传递和响应

    1.事件的产生和传递

    1.1事件的产生

    1.发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的队列事件中
    2.UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常会先发送事件给应用程序的主窗口(keyWindow)
    3.主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件

    1.2事件的传递

    触摸事件的传递是从父控件传递到子控件。事件传递给窗口或者控件后,就调用hitTest:withEvent:方法寻找更合适的view。方法底层会调用pointInside:withEvent:方法判断点在不在方法调用者的坐标系上,如果返回YES说明点在当前view上,继续通过hitTest:withEvent:方法遍历子控件,直到找到最合适的view。如返回NO,代表事件不在view内,直接返回nil,说明当前view不是最合适的view,其以下的子控件也都会被忽略。
    这个方法会忽略以下情况:

    • 视图是隐藏的 hidden = YES
    • 用户交互是关闭的 userInteractionEnabled = NO
    • 透明度小于0.01的 alpha < 0.01

    2.事件的响应

    • 响应者链条
      在ios程序中每个控件的摆放是有前后关系的,这种先后关系构成的一个链条就叫响应者链。
    • 响应者链的事件传递过程
      1.如果当前view是控制器的view,那么控制器就是上一个响应者,事件就传递给控制器;如果当前view不是控制器的view,那么父视图就是当前view的上一个响应者,事件就传递给它的父视图
      2.在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给window对象进行处理
      3.如果window对象也不处理,则其将事件或消息传递给UIApplication对象
      4.如果UIApplication也不能处理该事件或消息,则将其丢弃

    相关文章

      网友评论

          本文标题:事件传递和响应机制

          本文链接:https://www.haomeiwen.com/subject/munfjftx.html