Swift SKSpriteNode: Tap / DoubleTap / LongPress Discovery

I am trying to create a subclass of SKSpriteNode that can detect user interaction (tap, double tap and hold) and then set aside for delegate. This seems to me a relatively common need, but:

  • The code is not able to detect a double click without causing a single click.
  • I did not find a way to detect hold / long-press actions at all.

Am I really doing all this wrong? I can't help but feel that SpriteKit needs to have something standard to handle something so simple. I know that UIGestureRecognizer, but it does not seem very compatible with certain SKNodes, and not with UIViews.

Here is what I have now. Based on Apple's examples, I have all the non-device 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)
    }
}

... , iOS, :

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)
            }
        }
    }
}
+4
2

, , :

1 - var alreadyTouch false,

2 - touchesBegin, alreadyTouch false true ,

3 - Timer 0,2 if else, , . , alreadyTouch = true.

,

+3

touch.tapCount touchesBegan:

+3

All Articles