【翻译】About the Gesture Recognizer State Machine关于Gesture Recognizer 的状态机
—-学习Gesture Recognizer底层的state 和 state 的转变。
概述
Gesture Recognizer被状态机驱动(state machine),UIKit也用 ta 来保证正确处理事件。状态机决定了几个重要的行为:
- Gesture Recognizer是否被允许进入
UIGestureRecognizerStateBegan状态? - Gesture Recognizer是否被允许进入
UIGestureRecognizerStateEnded状态?(这个是 end,上面的是 began) - 什么时候调用action 函数?
自定义一个 Gesture Recognizer 时,你必须在合适的时候更新状态机。一个 Gesture Recognizer 永远都是从UIGestureRecognizerStatePossible开始,表示 ta已经准备好可以处理事件了。分离的和连续的 Gesture Recognizer 会经过不同的路径到达UIGestureRecognizerStateEnded, UIGestureRecognizerStateFailed, 或者UIGestureRecognizerStateCancelled 状态,Gesture Recognizer 会待在这几个状态之一,直到事件序列结束。
最后,UIKit 会重置 Gesture Recognizer ,并让它回到 UIGestureRecognizerStatePossible状态。
分离型 Gesture Recognizer 的状态转变
对于自定义的、分离的Gesture Recognizer ,ta 有两种状态UIGestureRecognizerStateEnded 或 UIGestureRecognizerStateFailed。下图展示了它的转变路径。当不断到来的事件匹配到了你写的手势,识别器会转到UIGestureRecognizerStateEnded,当匹配失败时,转到UIGestureRecognizerStateFailed。

图文似乎有点不符,右侧圆圈内应为「Ended」。
当转到结束的状态时(UIGestureRecognizerStateEnded),UIKit会调用所有关联目标对象的 action 函数。
如果转到的是失败的状态(UIGestureRecognizerStateFailed),不调用任何函数。
想了解实际例子的,请看「实现一个分离的Gesture Recognizer」 。
连续的 Gesture Recognizer 的状态转变
先看图

- 初始的事件序列会将Gesture Recognizer 转到
UIGestureRecognizerStateBegan 或 UIGestureRecognizerStateFailed状态
- 接下来的事件序列会让 ta 转到
UIGestureRecognizerStateChanged或UIGestureRecognizerStateCancelled - 最后是
UIGestureRecognizerStateEnded
如果初始事件序列不能匹配上你写的手势,那Gesture Recognizer 会直接从 possible 到 failed。正常情况下,UIKit 一次只允许一个Gesture Recognizer 通知 client(也就是在定义时写好的 target)。一个Gesture Recognizer 失败了,就会给其他Gesture Recognizer 一次处理它们手势的机会。
如果初始事件序列匹配上了你的手势,Gesture Recognizer会转到UIGestureRecognizerStateBegan状态,对于后续的事件,会重复地转到UIGestureRecognizerStateChanged状态,表示事件信息已经改变(即便 state 已经是 changed 的取值了,也要不断地设置 state 状态,因为「设置 state」这个动作会触发对应的 action 函数)。最后,就是成功识别就把 state 置为ended ,失败就置为cancelled。当Gesture Recognizer的state 被置为began、changed和ended 三者之一时,UIKit都会调用 action 函数。否则,不调用任何函数。
要了解实际例子,看「实现一个连续的Gesture Recognizer」
处理「取消操作」
当「系统事件」中断了「事件序列」时(比如有电话打进来)手势取消就发生了。也可以事件序列中的信息或者App 中的其他条件,用代码取消手势。「取消」会防止Gesture Recognizer执行某些用户并不想做的操作。
当系统取消手势时,UIKit 会调用touchesCancelled:withEvent: , pressesCancelled:withEvent:。同时,马上把Gesture Recognizer的 state 置为 cancelled,UIKit 会调用 action函数最后一次。随即重置(见下)。
重置Gesture Recognizer 的状态机
实现reset方法,让你的Gesture Recognizer回到初始配置。例如,用这个方法来把识别器的属性置为初始值,在处理新的事件序列前,UIkit 会调用符合以下条件的Gesture Recognizer的reset 函数:
- 接收touch 事件的
- 处在failed、ended 和cancelled 状态的
除了调用 reset 函数,UIKit 会自动修改每一个UIGestureRecognizerStateFailed 的 state 为possible 状态,以便它们能响应新的事件序列。
总结:不同类型的Gesture Recognizer的状态机转变路径是不一样的;手势取消也会调用 一次action 函数;处理新的事件序列前可以重置一下Gesture Recognizer。