【问题标题】:Swift SKSpriteNode: Detect Tap / DoubleTap / LongPressSwift SKSpriteNode:检测 Tap / DoubleTap / LongPress
【发布时间】:2014-09-28 21:01:18
【问题描述】:

我正在尝试创建一个 SKSpriteNode 的子类,它可以检测用户交互(点击、双击和按住),然后遵从委托。在我看来,这似乎是一个相对普遍的需求,但是:

  1. 代码无法在不触发单击的情况下检测到双击。
  2. 我还没有找到检测按住/长按操作的方法。

这一切都错了吗?我不禁觉得 SpriteKit 应该有一些标准来处理如此基本的事情。我知道有 UIGestureRecognizer,但它似乎与特定的 SKNodes 而不是 UIViews 兼容。

这是我目前拥有的。根据 Apple 的示例,我在主类文件中有所有非设备特定的代码:

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

【问题讨论】:

  • 通常当我需要一个必须检测用户点击的对象时,我使用 SKNode,它工作得更好,我在使用 SKSpriteNode 时遇到了很多问题。对于 iOS 特定代码,我将其添加到类本身,这样效果更好。
  • 感谢 Totka 的回复,但您不会在 SKNode 中也遇到同样的问题吗?您如何检测双击和长时间保持而不是单击?我担心的是,我的代码可能与识别此类基本用户输入的最佳实践相去甚远。
  • 我建议您使用内置的 UIGestureRecognizers,因为它们支持长按和双击(单击拒绝)。
  • 谢谢。虽然正如我上面提到的,UIGestureRecognizers 似乎与 SpriteKit 节点不兼容:没有添加它们的函数。这就是为什么我不相信我的设计的原因。一直在阅读有关 MVC 的更多信息,也许我应该研究如何在视图级别添加识别器,然后检测从那里点击了哪个节点?
  • 嗨。感谢您在流行的 uiscrollview 问题上添加 ios,但由于它的编辑太小,您可能很快就会面临其他审阅者的拒绝。最好还审查整个帖子以进行改进和/或在大规模编辑时等待 2000 名。

标签: ios user-interface swift sprite-kit skspritenode


【解决方案1】:

您可以在touchesBegan: 中简单地使用touch.tapCount

【讨论】:

  • 效果很好。请注意,这不会阻止第一次触摸事件触发,例如tapCount==1 触摸在touchesBegantouchesEnded 上仍然触发。所以你仍然需要锻炼,可能使用定时器,延迟识别它是真正的单击还是双击。
【解决方案2】:

我从来不需要检测双击,但如果我有,我会这样做:

1 - 添加一个名为 alreadyTouch 的本地变量,并在类初始化时将其设置为 false

2 - 在 touchesBegin 内部,如果 alreadyTouchfalse 将其设置为 true 否则做你必须做的事情

3 - 设置 0.2 秒的本地 Timer 并将其添加到 if else 以检测触摸是否足够快。所以在你设置alreadyTouch = true的地方启动这个计时器。

希望对你有帮助

【讨论】:

  • 您好 Totka,请您提供一些示例代码行,例如您将如何运行本地 Timer?
  • 你好,很抱歉,我失去了那个项目,或者更好的是,那个项目的高清
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-19
  • 2014-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多