I am trying to create a UIGestureRecognizer
subclass, and in touchesMoved
I have no code, yet state
is being set to .changed
.
Does anyone know why this is happening? I need to be able to decide for myself when we are in the .changed
state.
If I remove my touchesBegan
function and never move to .began
, this doesn't happen.
import UIKit.UIGestureRecognizerSubclass
class MyRecognizer: UIGestureRecognizer {
private var refView: UIView? {
return self.view?.window
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesBegan(touches, with: event)
if touches.count != 1 {
state = .failed
return
}
guard let location = touches.first?.location(in: refView) else {
self.state = .failed
return
}
state = .began
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
// there is no code here!
}
//This is how I'm debugging state
override var state: UIGestureRecognizerState {
get { return super.state }
set {
super.state = newValue
print("state = \(newValue.debugDescription)")
}
}
}
extension UIGestureRecognizerState: CustomDebugStringConvertible {
public var debugDescription: String {
switch self {
case .began: return "began"
case .possible: return "possible"
case .changed: return "changed"
case .ended: return "ended"
case .cancelled: return "cancelled"
case .failed: return "failed"
}
}
}
Your testing approach is flawed. I tried this (this is my test app's complete code):
import UIKit
import UIKit.UIGestureRecognizerSubclass
class MyRecognizer: UIGestureRecognizer {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesBegan(touches, with: event)
print(self.state.rawValue)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesMoved(touches, with: event)
print(self.state.rawValue)
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let g = MyRecognizer(target: self, action: #selector(grFired))
self.view.addGestureRecognizer(g)
// Do any additional setup after loading the view, typically from a nib.
}
@objc func grFired(_ g:UIGestureRecognizer) {
print("here", g.state.rawValue)
}
}
Then I dragged on the background view, to which the gesture recognizer is attached. My gesture recognizer never moved from the possible
state.
Also note that your expectations may be incorrect ("I need to be able to decide for myself when we are in the .changed state"). The normal and correct behavior is that, having declared the state to be .began
in touchesBegan
, your touchesMoved
will be called once with state .began
and the gesture recognizer will immediately advance to .changed
automatically. That is correct ; if this is continuous gesture, it cannot be the case that a moved
event should come in while we are in .began
state without our proceeding to .changed
. Again, here's a test:
import UIKit
import UIKit.UIGestureRecognizerSubclass
class MyRecognizer: UIGestureRecognizer {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesBegan(touches, with: event)
if touches.count != 1 {
state = .failed
return
}
print(self.state.rawValue)
self.state = .began
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesMoved(touches, with: event)
print("moved", self.state.rawValue)
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let g = MyRecognizer(target: self, action: #selector(grFired))
self.view.addGestureRecognizer(g)
// Do any additional setup after loading the view, typically from a nib.
}
@objc func grFired(_ g:UIGestureRecognizer) {
print("here", g.state.rawValue)
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.