UIGestureRecognizerState.Cancelled 对比 UIGestureRecognizerState.Failed

UIGestureRecognizerState.Cancelled vs UIGestureRecognizerState.Failed

.Cancelled.Failed 状态有什么区别?

将手势识别器的状态设置为 .Cancelled.Failed 对手势识别器本身有何影响?

手势识别器的状态何时变为 .Cancelled.Failed

手势识别器在什么时候被标记为 'recognized'?过渡到 .Began 之后?

如果是,手势的状态是否也可以在touchesMoved中设置为.Began

例如UIPinchGestureRecognizer在哪个阶段识别捏合手势?我猜只在 touchesMoved 因为捏是一个连续的手势。

以下是

之间的区别

.Cancelled

The gesture recognizer has received touches resulting in the cancellation of a continuous gesture. It sends its action message (or messages) at the next cycle of the run loop and resets its state to UIGestureRecognizerStatePossible.

.Failed

The gesture recognizer has received a multi-touch sequence that it cannot recognize as its gesture. No action message is sent and the gesture recognizer is reset to UIGestureRecognizerStatePossible.

换句话说,.Cancelled在连续手势被打断时被调用。 .Failed 当手势未被识别为某种类型的手势时调用。

实际上.Cancelled 和.Failed 状态之间没有区别。两者都导致手势识别器无法处理手势。我想这只是一个命名约定。

不过,不同之处还在于两种状态如何影响手势处理。

这取决于手势识别器的先前状态。

  1. 如果手势识别器在 touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent)(触摸的 UITouchPhase.Began 阶段)从 .Possible 过渡到 .Began,则与 .Failed.Cancelled,队列中的下一个手势识别器(附加到视图)将有机会处理该手势。不会发送任何操作消息。
  2. 但是如果手势识别器在 touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent)(触摸的 UITouchPhase.Began 阶段)从 .Possible 过渡到 .Began,则比在 touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent) 方法中过渡到 .Failed.Cancelled 手势识别将完全失败,什么也不会发生。但是无论如何都会发送操作消息。
  3. 如果注释掉第 8 行的代码,那么手势识别将失败,下一个附加到视图的手势识别器将有机会处理该手势。

所以这里是视图控制器:

class ViewController: UIViewController {

    func panHandler(sender: UIPanGestureRecognizer) {
         print("panHandler")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let customRecognizer = CustomGestureRecognizer(target: self, action: #selector(ViewController.customHandler(_:)))
        view.addGestureRecognizer(customRecognizer)

        let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(ViewController.panHandler(_:)))
        view.addGestureRecognizer(panRecognizer)

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func customHandler(c: CustomGestureRecognizer) {
        print("customHandler")
    }
}

这里是自定义手势识别器:

import UIKit
import UIKit.UIGestureRecognizerSubclass

class CustomGestureRecognizer: UIGestureRecognizer {

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent) {
        super.touchesBegan(touches, withEvent: event)
        state = .Began
        if touches.count == 1 {
            //state = .Failed
        }
        print("CustomGestureRecognizer.touchesBegan")
    }

    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent) {
        super.touchesMoved(touches, withEvent: event)

        if state == .Failed {
            return
        }

        if touches.count == 1 {
            state = .Failed //.Cancelled
        }

        state = .Changed
        print("CustomGestureRecognizer.touchesMoved")
    }

    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent) {
        super.touchesEnded(touches, withEvent: event)
        state = .Ended
        print("CustomGestureRecognizer.touchesEnded")
    }
}

只需 comment/uncomment 第 8、10 和 23 行的代码即可查看差异。