IOS中的触摸事件的处理

  IOS中的事件

  用户在使用app的过程中,会产生各种各样的事件。ios的事件可以分为3大类型:触摸事件 加速计事件 远程控制事件 。在IOS7的官方文档UI事件类型:

                     typedef enum{

          UIEventTypeTouched,//触摸事件

            UIEventTypeMotion,//加速计事件

            UIEventTypeRemoteControl,//远程控制事件

        }UIEventType;

  响应者对象

    在ios中不是任何的对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事件。我们称之为"响应者对象"。

    UIApplication、UIViewController、UIView都继承自UIResponder,因此它们 都是响应者对象,都能够接收并处理事件 。

  UIResponder

     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; 

 

    UIView的触摸事件处理

    UIview是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 

 

    UITouch

  当用户用一根手指触摸屏幕的时候,会创建一个与手指相关联的UITouch对象,也就是说一根手指对应一个UITouch对象。

    UITouch的作用

  保存着和手指相关的信息,比如触摸是位置,事件,阶段等等,这些都是在处理触摸事件的过程中很重要的属性,当离开屏幕的时候就会销毁这些对象了

    UITouch的属性

  

  @property(nonatomic,readonly) NSTimeInterval      timestamp;

  @property(nonatomic,readonly) UITouchPhase        phase;//当前触摸事件所处的状态

  @property(nonatomic,readonly) NSUInteger          tapCount;   // 短时间内点击屏幕的次数,可以用来判断单击双击或更多的点击次数

 

  @property(nonatomic,readonly,retain) UIWindow    *window;//触摸时所处的窗口

  @property(nonatomic,readonly,retain) UIView      *view;//触摸产生所处的视图

  @property(nonatomic,readonly,copy)   NSArray     *gestureRecognizers NS_AVAILABLE_IOS(3_2);//手势识别器集合

  UITouch的方法

  -(CGPoint)locationInView:(UIView *)view;

  返回值表示触摸在view上的位置,这里的返回值的坐标系采用的是UIKit的坐标系,也就是坐标原点在左上角,如果这里的view为Nil那么的返回的是触摸点在UIWindow的位置。

  -(CGPoint)previousLocationInView:(UIView *)view;

  该方法记录了前一个触摸点的位置。

  事件的产生和传递

  发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中去。UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常先发送事件给应用程序的主窗口
而主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件,这也是整个事件处理过程中的第一步。在找到合适的视图之后就会调用这个视图的touchesBegin,Moved,Ended三个方法来处理,至于这个
查找最合适的视图的过程还是比较复杂的。
                                
  上图是比较合适的表示方式:
  触摸事件的传递是从父控件传递到子控件:如果点击了绿色的view那么整个事件的传递过程就是
            UIApplication->UIWindow->白色的控制器View->绿色的view
  如果点击了蓝色的view: 
            UIApplication->UIWindow->白色view->橙色view->蓝色view
  在这个过程中有很重要的一点原则是寻找最合适的view来处理事件,查找的原则是:1.自己能否处理这个事件.2.触摸点是否在自己的身上。然后从后往前遍历自己子控件并且重复12两个步骤
如果没有符合条件的子控件,那么就自己进行处理,其实就是一个不断递归的过程。还有很重要的一点需要注意:如果父控件不能接受触摸事件,那么它的子控件就不可能接受到事件。这个原则在
查找控件不能点击的原因的时候是很有用的一个原则。

  响应者链条

  可以这么来理解,响应者链条就是一些列存在依赖继承关系的响应者来组成的处理响应事件的链条。

  IOS7官方文档这这一段:控制器是UIResponder的子类,所以具有了处理事件的能力。当一个视图不去处理一个给定的事件的时候,它就将这个事件传递给它的父控件,如果一直

没有得到处理就会到达根控制器,这样的话就会出现这样的情况,一个控制器处理了一个不属于它的直接的view的事件,当然如果这个控制器还是没有处理这个事件,这个事件还是会向

上进行传递。如果在视图层次结构的最顶级视图,如果也不能处理接收到的事件或消息,那么就将事件或消息传递给window进行处理,如果window对象也不处理,则将事件或者消息

传递给UIApplication进行处理,退一步将如果在application级别也没有处理就丢弃这个消息或者事件

  响应者链条决定了一个app中的事件是如何进行传播的

 
  NOTE:
    控制器和控制器的view之间信息传递的关系是被控制器进行私有管理的,不能通过函数改变的方式被应用改变。

 响应者链条的存在对于一个事件或者消息影响不同的view的情况提供了简单的方式

  如果想要将自己接收到的事件或者消息同时影响自己的父控件那么只需要在自己的事件处理方法中调用super的方法就能进行message-pass了。这样的过程和事件的传递的过程有点

相反的意味,就算这么理解也是没有太大的影响的。

 

 

 

 

2014年04月24日00:09:40

  

 

      

posted @ 2014-04-24 00:10  一壶浊酒  阅读(121)  评论(0)    收藏  举报