用户
 找回密码
 立即注册

发帖

iOS的事件处理(一)

[复制链接]
  • TA的每日心情
    慵懒
    2025-11-24 10:46
  • 27

    主题

    6

    回帖

    669

    积分

    管理员

    积分
    669
    发表于 2017-1-20 09:30:17
    最近把 Event Handling Guide for iOS 看了几遍,算是对 iOS 的事件处理有了个整体的概念,本文较长,可以先看后面的总结部分。对于事件处理,我们最熟悉的莫过于下面的Target-Action模式代码。
    1. UIControl / f8 `7 C  ^" ?: Z+ K' |# L- f- q
    2. addTarget:action:forControlEvents:3 ]9 v( }5 d) R
    3. 3 o2 w( I% ^8 {
    4. UIGestureRecognizer; p* n# H$ G1 ?  [; H( c
    5. initWithTarget:action:
    复制代码

    5 N' y: \6 F5 J8 A* b
    这些都是比较高级的用法了,因为 UIKit 都帮我们处理了,Gesture recognizers convert low-level event handling code into higher-level actions.低级的事件处理就是所谓的自定义事件处理。在这之前,我们先谈谈 iOS 中表示事件的相关类。
    一些重要的类UIEvent
    A UIEvent object (or, simply, an event object) represents an event in iOS. 在 iOS 中,事件是由UIEvent类表示的,大致可以分为四种类型
    1. typedef NS_ENUM(NSInteger, UIEventType) {
      ! b9 T& x3 X% D' f+ G; \
    2.     UIEventTypeTouches, // 触摸事件,按钮、手势等
      # f  r" N1 y; O
    3.     UIEventTypeMotion, // 运动事件,摇一摇、指南针等
      + C" v  M! m0 P8 m! j/ L
    4.     UIEventTypeRemoteControl, // 远程控制,耳机等
      ! f) u* G3 X( f( f: v5 }
    5.     UIEventTypePresses NS_ENUM_AVAILABLE_IOS(9_0), // 3D touch8 o0 c7 e/ r5 M# h7 G
    6. };
    复制代码

    8 s, ^+ p" R8 Q1 e# }( g
    这里只说 UIEventTypeTouches 触摸事件(注:本文所说的事件都是触摸事件)。 event 里面包含一个或者多个 touch (代表手指触摸屏幕,由 UITouch 类表示,下面会说)。当触摸事件发生时,系统会将它路由到合适的响应者,然后通过 UIResponder 的 touchesBegan:withEvent: 等方法传递。系统会评估这个事件并且找到合适的对象来处理它(包括hit-testing和first responder),一般情况下,我们不需要做特殊的处理。所以 UIEvent 类里面有多个获取 UITouch 对象的方法:
    1. - (nullable NSSet <UITouch *> *)allTouches;
      - t7 P6 W9 `$ P9 `
    2. - (nullable NSSet <UITouch *> *)touchesForWindow:(UIWindow *)window;
      # }. A& H& X- O- ~8 Z
    3. - (nullable NSSet <UITouch *> *)touchesForView:(UIView *)view;
      + J9 c6 U# V7 d. ?/ [4 T  _( ]8 z
    4. - (nullable NSSet <UITouch *> *)touchesForGestureRecognizer:(UIGestureRecognizer *)gesture NS_AVAILABLE_IOS(3_2);; n/ m$ s" ~  ~- r
    5. - (nullable NSArray <UITouch *> *)coalescedTouchesForTouch:(UITouch *)touch NS_AVAILABLE_IOS(9_0);, j6 A0 C5 N4 m' j2 \* i
    6. - (nullable NSArray <UITouch *> *)predictedTouchesForTouch:(UITouch *)touch NS_AVAILABLE_IOS(9_0);
    复制代码
      {6 h4 X& w. a( V/ U, s1 }, i' R
    这里有两点需要注意一下:
    • timestamp 属性,这个时间戳是从系统开机后开始算的。相关事件处理,可以看Peak君的iOS关于时间的处理
    • You should never retain an event object or any object returned from an event object. 不要持有事件对象或者从事件 对象中返回的对象。因为 UIEvent 对象在多点触摸序列(指手指触摸屏幕到离开屏幕)中是持久的, UIKit 会重用 UIEvent 对象,如果你需要持有 event 或者 touch 的相关信息时,你可以拷贝相关信息,赋值给相关变量。
      % s0 V2 s4 t5 L' x# w& h! l3 Y
    UITouch
    它代表手指触摸到屏幕上的位置,大小等相关信息。一个手指代表一个 UITouch 对象,所以可以根据tapCount属性来判断是单击、双击、三击。根据 touch 可以我们可以得知
    • The view or window in which the touch occurred (touch 发生所在的 view 或者 window)
    • The location of the touch within the view or window (touch 发生所在的 view 或者 window 上的位置)
    • The approximate radius of the touch
    • The force of the touch (on devices that support 3D Touch or Apple Pencil)
      * [6 T) y2 V! I2 x8 o2 G# O4 w* r
    当然还可以知道接受该 touch 对象的 gestureRecognizers 手势识别器。
    我们还可以根据 phase 属性获取 touch 的相关状态。
    1. UITouchPhaseBegan: A finger for a given event touched the screen.9 w) h5 p* J, U! {
    2. UITouchPhaseMoved: A finger for a given event moved on the screen.
      & M  d6 C6 S# ~1 a3 C$ ?6 S
    3. UITouchPhaseStationary: A finger is touching the surface but hasn't moved since the previous event.) t# o. K5 k% j  L# \
    4. UITouchPhaseEnded: A finger for a given event was lifted from the screen.
      4 v! u( y. v* J5 K
    5. UITouchPhaseCancelled: The system canceled tracking for the touch, as when (for example) the user moves the device against his or her face.
    复制代码

    8 u, f2 M! k9 f' J4 P% r
    除了 UITouchPhaseStationary 状态以外,每个状态都对应着 UIResponder 的touchXxxxx:withEvent:类似的方法。拿到 UITouch ,我们就可以指定这个触摸事件所在的 view 以及位置。拿到位置以后,我们就可以做我们想要做的事情了。
    UIResponder
    The UIResponder class defines an interface for objects that respond to and handle events. It is the superclass of UIApplication, UIView and its subclasses (which include UIWindow). Instances of these classes are sometimes referred to as responder objects or, simply, responders. 它定义了响应和处理事件的接口。像一些能够处理相应事件的类(UIApplication, UIView 等)都是它的子类。
    1. // 处理触摸事件的主要方法,所以我们自定义事件处理时,就需要在这几个方法里面做文章。5 {: t/ I" l  A& l; h! Z, q
    2. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; // 一根或者多跟手指开始触摸屏幕2 X' f$ l6 O- v& R' Q/ x' L  o/ P+ Z
    3. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; // 手指在屏幕上移动
      % S+ C# c0 O6 `; [! m2 F
    4. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; // 手指离开屏幕
      7 r3 k, O* C5 {8 R
    5. - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event; // 收到系统的事件(如,来电话了或者低内存警告等)取消触摸事件
    复制代码
    6 e. c* @! k6 v# }% L. S0 }
    只要手指触摸在屏幕上,不管是手指拖动还是离开屏幕, UIEvent 对象就会生成,而它由包含相关的 UITouch 对象。入参说明:
    • touches。这个状态新的或改变的 touches 。
    • event。代表这个事件 event 的所有 touches ,所以上面的 touches 也属于它。This differs from the set of touches because some of the touch objects in the event may not have changed since the previous event message. 它跟上面的 touches 的区别就在于它可能包含发生改变的 touch 。强调一个状态的改变。
      : N1 Z* j4 A9 s8 c1 s; `
    1 f6 @5 o: b1 \7 g1 a
    使用道具 举报 回复
    严禁恶意灌水!!!拒绝伸手党!!!
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    ض