I'm attempting to create a subclass of SKSpriteNode which can detect user interaction (tap, double tap and hold), then defer to a delegate. This seems to me like a relatively common need, but:
- The code is incapable of detecting a double-tap without also triggering a single-tap.
- I haven't found a way to detect hold/long-press actions at all.
Am I going about this all wrong? I can't help feeling that SpriteKit should have something standard to handle something so basic. I know there's UIGestureRecognizer, but it doesn't seem very compatible with specific SKNodes rather than UIViews.
Here's what I have currently. Based on examples from Apple, I have all of the non-device-specific code in the main class file:
import SpriteKit
enum ActionType: Int {
case Single
case Double
case Hold
}
protocol EnvironmentElementDelegate {
func handleActionOnElement(element: EnvironmentElement, actionType: ActionType)
}
class EnvironmentElement: SKSpriteNode {
let delegate: EnvironmentElementDelegate!
init(imageNamed: String, elementNamed: String, delegate: EnvironmentElementDelegate) {
self.delegate = delegate
let texture = SKTexture(imageNamed: imageNamed)
super.init(texture: texture, color: UIColor.clearColor(), size: texture.size())
self.name = elementNamed
userInteractionEnabled = true
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
...then all of the iOS-specific code in a separate extension file:
import SpriteKit
extension EnvironmentElement {
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
for touch: AnyObject in touches {
if (touch.tapCount >= 2) {
NSObject.cancelPreviousPerformRequestsWithTarget(self)
}
}
}
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
for touch: AnyObject in touches {
if (touch.tapCount == 1) {
delegate.handleActionOnElement(self, actionType: ActionType.Single)
// Unable to find Swift equivalent to this: [self performSelector:@selector(onFlip) withObject:nil afterDelay:0.3];
} else {
delegate.handleActionOnElement(self, actionType: ActionType.Double)
}
}
}
}
You can simply use touch.tapCount
inside touchesBegan:
I never had to detect a double tap, but if I have I will do it like this:
1 - add a local var named alreadyTouch
and set it to false
when the class is initialized
2 - inside touchesBegin
if alreadyTouch
is false
set it to true
else do what you have to
3 - setup a local Timer
of 0.2 seconds and add also this to the if else to detect if the touch is rapid enough or not. so start this timer where you set alreadyTouch = true
.
Hope it helps
来源:https://stackoverflow.com/questions/26089619/swift-skspritenode-detect-tap-doubletap-longpress