Event官方文档

  1. Event是对象,它代表了一个被硬件检测到的用户行为,并且该行为传递到iOS中。
  2. UIKits当下可以识别三种类型的events:touch事件、shaking事件和remote-control事件(比如耳机控制)
  3. 永远不要retain UIEvent对象。
  4. Event Delivery流程:
    a) 当用户touch手机屏幕时,iOS识别了touch并打包到UIEvent对象里,并排到active application的事件队列之中。
    b) 如果刺痛将shaking解析为一个motion event。 UIApplication 单例,就是会管理application的那个,会从队列top取出来一个event 对象并且dispatch,转发给handler。
    c) 一般来说,UIApplication会转发给application的key window,然后window会发送这个event给一个初始化的obj以便处理。这个对象会区分为touch event和motion event:
    i. touch event:window obj 用hit-testing和响应链来寻找响应事件的对象。在hit-testing里,window会调用hitTest:withEvent:方法在view 树最上层的view上。这个方法会递归的调用pointInside:withEvent方法在view树的每一个会返回YES的view中。这个过程会一直进行,直到发现某个view在touch的范围内,这个view就变成了hit-testview。如果hit-test view没办法处理事件,则事件就会沿着响应链一路向上知道系统发现一个能处理的view
    ii. motion 和 remote-control事件:window会发送每一次的shaking-motion或者remote-control事件给first responder去处理。
  5. UIApplication对象和每一个UIWindow对象会通过sendEvent方法来派发事件。由于这些方法都是event 进入application的funnel points,所以你可以继承UIApplication或者UIWindow并且重载sendEvent方法来监控事件。如果你真的重载了,一定记得要调用super方法([super sendEvent:the Event]).
  6. UIResponse是所有responder对象的基类。它不仅仅定义的编程接口不仅为了事件处理,还为了普通响应行为。
  7. 继承链:

    当系统传递一个touch event,首先会send到一个特定的view。对于touch view来讲,这个view就是被hitTest:withEvent:返回的view;对于shaking-motion event,remote-control事件,action messages,和editing-menu message, view就是firstResponder。如果initial view没有处理event,他就会沿着响应链去查找,顺序为:
    a) hit-test view或者firstResponder会传递event或者message到它的vc上(如果有的话);如果没有vc,则将event或者message传到superView上
    b) 如果view或者vc不能handle event或者message,会传到view的superview上。
    c) 之后的所有superView会根据a、b的模式进行传输,如果无法handle的话
    d) view树的最上层的view,如果无法handle event或者message,会把event send到window对象
    e) 如果UIWindow对象无法handle的话,会传递到application对象单例上
    f) 如果application单例无法处理event或者message,则discards。

  8. 如果想要接收并处理高频率的,连续的motion data,应当使用 Core Motion accelerometer API。
  9. 触摸行为,被UITouch 对象表示,有时间和空间特性。时间特性,称之为相位,暗示了何时触摸的开始,不论他是静还是动和何时触摸结束,当手指从屏幕上抽离。空间特性指的是touch会聚合很多对象,表征touch出现过的地方。
  10. Touch事件的传递需要注意的:
    a) 关掉touch事件的传递。 设置userInteractionEnabled属性为NO
    b) 关掉一定时间内的touch事件的传递。Application能调用UIApplication的beginIgnoringInteractionEvent,之后调用endIgnoringInteractionEvents方法。所以在展示animation的时候最好关掉事件传递。
    c) 限制事件传递到一个单个的view上。默认的,view的exclusiveTouch属性是NO,表示他会接收传递的事件。如果设置为YES,则在事件传递时,它不会接收事件。
    d) 限制事件传递至subviews。自定义UIViewclass会重载hittest:withEvent方法去限制multitouch事件至subview。
  11. 为了能接收multitouch事件,你的子类必须实现一个或多个UIResponder方法(touch-event handling)。另外,view必须可见(不能透明或者隐藏),并且userInteractionEnabled属性为YES。
  12. 存储UITouch应当用CFDictionaryRef而不是NSDictionary,因为之后的会copy 它的keys,而UITouch类没有实现NSCopying协议。
  13. 处理Multitouch事件的最佳实践:
    a) 实现event-cancellation方法。防止不连续的状态的出现。
    b) 如果处理的event是在UIView、UIViewController或者UIResponder的子类:
    i. 应当继承宿友event-handling方法;
    ii. 不要调用方法的super实现
    c) 如果处理的是其它UIKit responder类的实现,在:
    i. 不要实现任何event-handling方法;
    ii. 一定要调用super方法,如:[super touchBegan:theTouches withEvent:theEvent];
    d) 不要将event forwar到其它UIKit framework的responder 对象中。
    e) 自定义类,响应event是应当只在event-handling方法里设置drawing状态,并且只在drawRect方法里去绘图。
    f) 不要通过nextResponder去越级触发事件;相反,应当通过调用superClass实现来处理响应链。
  14. 手势识别中,在将事件send到hit-test view之前,window对象会把它send到和这个view或者view的subviews相关的手势识别器当中。过程如下所示。


  15. 一般来说,两个手势识别器不能同时识别手势。但是你可以通过实现gestureRecognizer:shouldRecognizeSimultaneouslyWIthGestureRecognizer:,是UIGestureRecognizerDelegate协议实现的。这个方法会在当接收器接阻断特殊识别器的操作时被调用。Return YES 当所有的手势识别器去同时识别他们的手势。
  16. Touch 事件的传递:(假设一个双指的触摸)
    a) Window发送连个touch 对象在 start phase(UITouchPhaseBegan)到手势识别器中,此时还未识别手势。Window会发同样的对象给手势关联的view。
    b) Window发送两个touch 对象在Move phase(UITouchPhaseMoved)到手势识别器中,此时还是未识别什么手势。Window会发同样的对象给手势关联的view。
    c) Window发送一个touch对象在End Phase(UITouchPhaseEnded)到手势识别器中。这个touch对象没有为确定手势获得足够的信息,但是window此时不会给关联view数据
    d) Window发送逆回购touch对象在End Phase。手势识别器现在识别了手势并且设置状态为UIGestureRecognizerStateRecognized.在第一个action msg发送之前,view收到了touchCancelled:withEvent:消息,使得之前发送的消息失效。 在End Phase的touch被取消了。
    e) 如果手势识别器检测到多指操作并非手势,会设置状态为UIGestureRecognizerStateFailed。
  17. 手势的状态转移
    a) 所有手势都开始于UIGestureRecognizerStatePossible。之后会分析多指触摸的顺序,通过他们的hit-test view,之后要么识别出来要么识别失败。如果没有识别成功,则转为UIGestureRecognizerStateFail。这条准则不论是离散手势还是连续手势,都适用。
    b) 当一个手势被识别时,连续手势的状态识别有别于离散手势。离散手势直接从Possible到Recognized(UIGestureRecognizerStateRecognized).。对于连续手势来讲,当最初识别手势,会从Possible到Began(UIGestureRecognizerStateBegan),当开始识别时。之后会从began到changd(UIGestureREcognizerStateChanged),之后每一次变化都会变为changed。最终,当最后一个手指离开屏幕时,状态变为End(UIGestureRecognizerStateEnded)。当然,也有可能会从changed到cancelled。
    c) 总结下来,分别如下图:

    d)
  18. 要想接收motion 事件,responder对象必须是firest responder。对象要继承UIResponder,必须不近实现motionBegan:withEvent:和motionEnded:withEvent方法,也有可能是都实现。
  19. shake事件和touch事件有很大不同。当用户开始shake设备,系统会发送motion事件给first responder,通过motionBegan:withEvent:消息。如果responder没有handle事件,则他会沿着响应链向上查找。如果shaking少于一秒,则系统会发送motionEnded:withEvent:消息给firstResponder。如果shake时间太长,系统认为不是一个shake,first responder会接收一个motionCancelled:withEvent:消息。
  20. 在获取当前方向之前,你需要告诉UIDevice类,去开始收集系统的旋转通知,通过调用beginGeneratingDeviceOrientationNotifications方法。这会打开加速器硬件。之后在处理完旋转的事件之后,你可以获取当前的旋转方向,(从UIDevice)。你也可以通过UIDeviceOrientationDidChangeNotification方法,来接收旋转的通知。
    在Remote-control事件的处理上,接收事件时需要将对象设置为first Responder,设置canBecomeFirstResponder去返回YES。也需要设置becomeFirstResponder:- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
    [self becomeFirstResponder];
    }
    当vc不在管理audio或者video时,应当关掉事件窗口,注销first Responder状态。
  • (void)viewWillDisappear:(BOOL)animated {
    [[UIApplication sharedApplication] endReceivingRemoteControlEvents];
    [self resignFirstResponder];
    [super viewWillDisappear:animated];
    }

你可能感兴趣的:(Event官方文档)