Swift SKSpriteNode: Detect Tap / DoubleTap / LongPress

不羁岁月 提交于 2019-12-07 06:56:25

问题


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:

  1. The code is incapable of detecting a double-tap without also triggering a single-tap.
  2. 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)
            }
        }
    }
}

回答1:


You can simply use touch.tapCount inside touchesBegan:




回答2:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!