Override UIgesturerecognizer Touchesbegan

Override UIGestureRecognizer touchesBegan

Ôh ! Here is the Swift code for nextResponder :

https://stackoverflow.com/a/26510277/4135158

Overriding touchesBegan: Error - method does not override any method from superclass

I was indeed using Xcode 7.2 with Swift 2.0. And removing the override keyboard was not the solution. Instead, I found that the solution was to add import UIKit.UIGestureRecognizerSubclass. That also allowed me to write over the state property, rather than it being read-only.

touchesBegan Vs UITapGestureRecognizer

so if you hold on the red square for two seconds you'll get a message, when you let go the message disappears. you might have to add some booleans in there to make sure your character isnt repeating some action every frame after the 2 second button hold. this should be enough to get you started hopefully

import SpriteKit

class GameScene: SKScene {

// time values
var delta = NSTimeInterval(0)
var last_update_time = NSTimeInterval(0)

var longTouchTimer = NSTimeInterval(0)
var touched = false
var testLabel = SKLabelNode(text: "you have touched for awhile now bro")

let touchSprite = SKSpriteNode(color: SKColor.redColor(), size: CGSizeMake(100, 100))

override func didMoveToView(view: SKView) {
touchSprite.position = CGPointMake(self.size.width/2, self.size.height/2)
addChild(touchSprite)

testLabel.hidden = true
testLabel.position = touchSprite.position
testLabel.position.y += 100
testLabel.fontSize = 20
addChild(testLabel)
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)

if touchSprite.containsPoint(location) {
touched = true
}
}
}

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)

if !touchSprite.containsPoint(location) {
touched = false
longTouchTimer = 0
}
}
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
touched = false
longTouchTimer = 0
}

override func update(currentTime: NSTimeInterval) {
if last_update_time == 0.0 {
delta = 0
} else {
delta = currentTime - last_update_time
}

last_update_time = currentTime

if touched {
longTouchTimer += delta
}

if longTouchTimer >= 2 {
testLabel.hidden = false
} else {
testLabel.hidden = true
}
}
}

How to replace TouchesBegan with UIGestureRecognizer

For what you are tryin ti do you can't. The gesture recoginizers are for high level gestures so they behaive the same across all apps (think swipes, the timing required for a double tap, etc). For low level control and to do things that the recognizers can't you will still have to implement logic in touchesbegan, touchesEnded, etc.

UIGestureRecognizer subclass-- touchesMoved automatically changes state to .changed

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)
}

}

UIPanGestureRecognizer does not have a member named touchesBegan

You don't have to override the functions, you can just define them like below. But I am not exactly sure why that is. In a custom UIView these functions have to be overridden.

func touchesBegan(touches: NSSet!, withEvent event: UIEvent!) {
println("here")
}

func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) {

}

func touchesEnded(touches: NSSet!, withEvent event: UIEvent!) {

}

func touchesCancelled(touches: NSSet!, withEvent event: UIEvent!) {

}

UIView touchesBegan won't fire when UILongPressGestureRecognizer minimumPressDuration zero

Despite the misuse of UILongPressGestureRecognizer for a scenario where UITapGestureRecognizer has to be used instead, I will focus on answering the "why" part.

When you set gesture.minimumPressDuration = .zero, the long-press gesture gets instantly recognized.

By default, gesture recognizers tend to delay touches in view, and cancel them if they recognize the gesture.

In order to override this behavior, set

gesture.cancelsTouchesInView = false // to recieve touchesBegan callback even if gesture is recognized
gesture.delaysTouchesBegan = false // to not delay touchesBegan callback
gesture.delaysTouchesEnded = false // to not delay touchesEnded callback


Related Topics



Leave a reply



Submit