ios事件之触摸事件

一、iOS事件

1.事件:当我们在手机上点击手机屏幕、滑动手机翻页、摇动手机的时候,手机会做出一些反应,对应的在应用程序里实现了某些代码的某些功能,完成这个过程就是一个事件。

2.iOS事件类型大致分为三大类型:


(1)触摸事件,比如点击照片放大、点击按钮等。

(2)加速计事件,比如微信摇一摇,通过手机的运动,实现某些功能。

(3)远程控制事件,比如插图中的第三种情况。

提示:在iOS中并不是所有的对象都能处理事件,只有继承于UIResponder才具有接收并响应事件的功能,我称它们为"响应者对象"

3.UIResponder 提供了一下的处理事件的方法

   1>触摸事件  (touches存放的是UITouch对象)

- (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;  
     //当触摸事件被电话呼入等事件取消时

提示:四个触摸事件处理方法中,都有NSSet* touches和UIEvent*event两个参数

(1)一次完整的触摸过程中,只会产生一个事件对象,4个触摸方法都是同一个event参数;

(2)如果两根手指同时触摸一个View,那么view只会调用一次touchesBegan: withEvent:方法,touches参数中装着两个UITouch对象;

(3)如果这两根手指一前一后分开触摸同一view,那么view会分别调用2次touchesBegan:withEvent:方法,且每次调用了touches参数中仅装着一个UITouch对象;

(4)根据touches中UITouch的个数,通过switch方法可以判断是单点触摸还是多点触摸.

(5)上面的四个事件方法,在开发过程中并不要求全部实现,可以根据需要重写特定的方法。因为UIEvent包含了整个触摸过程中所有的触摸对象,因此可以调用allTouches方法获取该事件内所有的触摸对象,也可以调用touchesForVIew:或者touchesForWindows:取出特定视图或者窗口上的触摸对象。在这几个事件中,都可以拿到触摸对象,然后根据其位置,状态,时间属性做逻辑处理。

 2>加速计事件

  - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event 
  - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event 
  - (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event

3>远程控制事件

  -(void)remoteControlReceivedWithEvent:(UIEvent*)event;

二、触摸事件之UITouch

1.UITouch触摸对象

当用户用一根触摸屏幕时,会创建一个与手指相关联的UITouch对象  一个手指对应着一个UITouch对象

UITouch存着手指相关的信息,比如触摸的位置,时间,阶段。

当手指移动时,系统会更新同一个UItouch对象,使之能够一直保存该手指所在的触摸位置
   当手指离开屏幕时,系统会销毁相应的UITouch对象
   提示:iPhone开发中,要避免双击事件!

2.UITouch常用属性和方法

(1)常用属性

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

提示:  phase是UITouchPhase类型的,它是一个枚举:

·  UITouchPhaseBegan

·  UITouchPhaseMoved

·  UITouchPhaseStationary

·  UITouchPhaseEnded

window、view、tapCount、phase都是UITouch类中常用属性,也就是说建立一个UITouch对象就可以用这些属性来看触摸事件包含的信息。

(2)常用的方法

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

参数:

 返回值 

   1>表示触摸在view上的位置(位置是以View本身的坐标系为参考,就是以view的左上角为原点)

   2>加入view传入的为nil,那么返回的是以UIWindow为坐标系的触摸位置.

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

参数:

 返回值

    前一个触摸点的位置

 - (CGPoint)preciseLocationInView:(nullable UIView *)view NS_AVAILABLE_IOS(9_1);
 - (CGPoint)precisePreviousLocationInView:(nullable UIView *)view NS_AVAILABLE_IOS(9_1);

参数:在ios9.1之后引入的,因为ios9.1之后引入了苹果笔.(不常用)

(3)实例

 实例一 触摸时,图片移动 

- (void)viewDidLoad  
{   [super viewDidLoad];  
    UIImageView *image = [[UIImageView alloc] initWithFrame:CGRectMake(20.0, 50.0, 45.0, 45.0)];  
    image.image = [UIImage imageNamed:@"baby.png"];  
    image.tag = 100;  
    [self.view addSubview:image];  
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event  {  
    UITouch *touch = [touches anyObject];  //取出一个触摸点
//UITouch类中有已经建立了很多UITouch对象,只需要从中取出来即可,不用重复创建,所以此处不用 alloc,用一个UITouch的对象touch接收就行了。anyObject是从类里面任意取出来一个。
    UIImageView *view1 = (UIImageView*)[self.view  viewWithTag:100];  
    CGPoint point = [touch  locationInView:self.view];  
    CGRect  frame = view1.frame;  
    frame.origin = point;  
    view1.frame = frame;  
}  

实例二  判断是双击还是单击

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event  {  
    UITouch *touch =  [touches anyObject];  
    if(touch.tapCount == 2)  {  
    self.view.backgroundColor = [UIColor redColor]; 
  }
  } 

 检测tapCount可以放在touchesBegan也可以touchesEnded,不过一般后者跟准确,因为touchesEnded可以保证所有的手指都已经离开屏幕,这样就不会把轻击动作和按下拖动等动作混淆。 

 轻击操作很容易引起歧义,比如当用户点了一次之后,并不知道用户是想单击还是只是双击的一部分,或者点了两次之后并不知道用户是想双击还是继续点击。为了解决这个问题,一般可以使用“延迟调用”函数。
  例如:

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event  {  
    UITouch *touch =  [touches anyObject];  
    if(touch.tapCount == 1)  {  
        [self performSelector:@selector(setBackground:) withObject:[UIColor blueColor] afterDelay:2];  
        self.view.backgroundColor = [UIColor redColor];  
    }  
} 
  上面代码表示在第一次轻击之后,没有直接更改视图的背景属性,而是通过performSelector:withObject:afterDelay:方法设置2秒中后更改。
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event  {  
    UITouch *touch =  [touches anyObject];  
    if(touch.tapCount == 2)  {  
      [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(setBackground:) object:[UIColor redColor]];  
      self.view.backgroundColor = [UIColor redColor];  
    }  
}  
  双击就是两次单击的组合,因此在第一次点击的时候,设置背景色的方法已经启动,在检测到双击的时候先要把先前对应的方法取消掉,可以通过调用NSObject类的cancelPreviousPerformRequestWithTarget:selector:object方法取消指定对象的方法调用,然后调用双击对应的方法设置背景色为红色。

三.触摸事件之UIEvent

1>触摸事件对象

UIEvent:事件对象,记录事件的时刻和类型.  没产生一个事件,就会产生一个UIEvent对象

2>常见属性

(1)事件类型

@property(nonatomic,readonly) UIEventType     type NS_AVAILABLE_IOS(3_0);
  @property(nonatomic,readonly) UIEventSubtype  subtype NS_AVAILABLE_IOS(3_0);

(2)事件产生的时间

@property(nonatomic,readonly) NSTimeInterval  timestamp;

四,响应者链

   (1)响应者对象(Response object)
          响应者对象就是可以响应事件并对事件作出处理。在iOS中,存在UIResponder类,它定义了响应者对象的所有方法。UIApplication、UIView等类都继承了        UIResponder类,UIWindow和UIKit中的控件因为继承了UIView,所以也间接继承了UIResponder类,这些类的实例都可以当作响应者。
      (2)第一响应者(First responder)
          当前接受触摸的响应者对象被称为第一响应者,即表示当前该对象正在与用户交互,它是响应者链的开端。
      (3)响应者链(Responder chain)
          响应者链表示一系列的响应者对象。事件被交由第一响应者对象处理,如果第一响应者不处理,事件被沿着响应者链向上传递,交给下一个响应者(next responder)。一般来说,第一响应者是个视图对象或者其子类对象,当其被触摸后事件被交由它处理,如果它不处理,事件就会被传递给它的视图控制器对象(如果存在),然后是它的父视图(superview)对象(如果存在),以此类推,直到顶层视图。接下来会沿着顶层视图(top view)到窗口(UIWindow对象)再到程序(UIApplication对象)。如果整个过程都没有响应这个事件,该事件就被丢弃。一般情况下,在响应者链中只要由对象处理事件,事件就停止传递。但有时候可以在视图的响应方法中根据一些条件判断来决定是否需要继续传递事件。
      (4) 管理事件分发
         视图对触摸事件是否需要作处回应的方法:

        1)userInteractionEnabled属性。默认状态为YES,如果设置为NO,可以阻止视图接收和分发触摸事件.

        2)设置视图被隐藏Hidden. Hidden属性为YES;

        3)设置透明度(alpha值为(0~0.1之间)也不会收事件。

   注意:  

    1)不过以上对视图有效,如果想要整个程序都不响应事件,可以调用UIApplication的beginIngnoringInteractionEvents方法来完全停止事件接收和分发。

       通过endIngnoringInteractionEvents方法来恢复让程序接收和分发事件。

    2)如果要让视图接收多点触摸,需要设置它的multipleTouchEnabled属性为YES,默认状态下这个属性值为NO,即视图默认不接收多点触摸。

    3)UIImageView的userInteractionEnabled默认是NO.即UIImageView以及它的子控件在默认状态下是不能接受触摸事件的

    4)touch事件的传递



响应者链示意图

五,关于手势与触摸事件的区别

 手势继承自UIGestureRecognizer-->NSObject。 而UITouch直接继承自NSObject。
    事实上,手势和UITouch本身关系不大,在IOS3.2之前根本没有手势,以前的所有操作都依赖于UITouch,这也是为什么UITouch定义在UIRsponder中的原因之一

 此外UIResponder及其子类都自带监听UITouch的方法。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
iOS开发中,触摸事件处理是非常重要的,因为用户与应用程序的交互主要是通过触摸屏幕来完成的。iOS提供了一整套触摸事件处理机制,包括手势识别、触摸事件响应等。下面我们来介绍一下iOS中常用的触摸事件处理方法。 1. 触摸事件响应方法 在iOS中,触摸事件主要由以下4个方法来响应: - touchesBegan:withEvent: //手指开始接触屏幕 - touchesMoved:withEvent: //手指在屏幕上移动 - touchesEnded:withEvent: //手指离开屏幕 - touchesCancelled:withEvent: //触摸事件取消 这些方法都在UIView类中定义,所以如果你的应用程序需要响应触摸事件,你需要重写UIView的这些方法。 2. 手势识别器 在iOS中,手势识别器是一种非常方便的触摸事件处理方式。手势识别器可以识别出一些常用的手势,比如轻击、长按、拖动、捏合等等,并且可以通过回调方法来处理这些手势。 手势识别器有很多种,比如UITapGestureRecognizer、UILongPressGestureRecognizer、UIPanGestureRecognizer、UIPinchGestureRecognizer等等。使用手势识别器可以让你的应用程序更加灵活,同时也可以提高用户体验。 3. 响应者链 在iOS中,事件的传递是通过响应者链来完成的。当用户发生了触摸事件时,事件会从最上层的UIWindow开始传递,直到找到第一个响应该事件的对象。如果没有任何对象响应该事件事件就会被丢弃。 因此,在处理触摸事件时,你需要注意响应者链的结构,确保事件能够正确地传递到你想要处理事件的对象。 总之,在iOS开发中,触摸事件处理是一个非常重要的部分,需要我们认真对待。通过合理地使用触摸事件处理方法和手势识别器,我们可以为用户提供更加灵活、友好的应用程序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值