You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Swift/SpriteKit中按钮TouchesEnded处理失效的问题?

SpriteKit按钮快速滑动点击后无法恢复原色

我用Swift/SpriteKit开发了一款iOS小型应用,其中包含一个按下时会变成绿色的黑色按钮。按钮正常点击时功能没问题,但如果快速半滑动半点击按钮,手指离开屏幕后按钮会一直保持绿色,无法恢复成黑色。

以下是我的代码:

//
//  GameScene.swift
//  box button only test 2025
//
//  Created by Chris Tucker on 3/30/25.
//

import SpriteKit
import GameplayKit

class GameScene: SKScene {
    
    let rightBox = SKSpriteNode(color: SKColor.black, size: CGSize(width: 100, height: 100))
    
    override func didMove(to view: SKView) {
        rightBox.position = CGPoint(x: 0, y: 0)
        rightBox.name = "rightBoxName"
        addChild(rightBox)
    }
    
    
    func touchDown(atPoint pos : CGPoint) {
     if rightBox.contains(pos) {
        rightBox.color = .green
        }
    }
    
    
    func touchMoved(toPoint pos : CGPoint) {
        if rightBox.contains(pos) {
            rightBox.color = .green
        } else { rightBox.color = .black }
    }
    
    func touchUp(atPoint pos : CGPoint) {
        if rightBox.contains(pos) {
            rightBox.color = .black // set
        }
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
      for t in touches { self.touchDown(atPoint: t.location(in: self)) }
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches { self.touchUp(atPoint: t.location(in: self)) }
    }
    
    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches { self.touchUp(atPoint: t.location(in: self)) }
    }
    
    
    override func update(_ currentTime: TimeInterval) {
        // Called before each frame is rendered
    }
}

问题原因

当前代码仅在手指抬起位置处于按钮内部时,才会将按钮恢复为黑色。但快速滑动场景下,touchesMoved可能未及时触发,或手指抬起时已移出按钮范围,导致按钮停留在绿色状态。且代码未跟踪按钮的按下状态,完全依赖触摸位置判断颜色,逻辑存在漏洞。

修复方案

添加布尔变量跟踪按钮的按下状态,触摸结束时无论手指位置如何,只要按钮曾被按下,就恢复原色。

修改后的代码:

import SpriteKit
import GameplayKit

class GameScene: SKScene {
    
    let rightBox = SKSpriteNode(color: SKColor.black, size: CGSize(width: 100, height: 100))
    // 新增变量跟踪按钮按下状态
    private var isRightBoxPressed = false
    
    override func didMove(to view: SKView) {
        rightBox.position = CGPoint(x: 0, y: 0)
        rightBox.name = "rightBoxName"
        addChild(rightBox)
    }
    
    func touchDown(atPoint pos : CGPoint) {
        if rightBox.contains(pos) {
            rightBox.color = .green
            isRightBoxPressed = true
        }
    }
    
    func touchMoved(toPoint pos : CGPoint) {
        if rightBox.contains(pos) {
            rightBox.color = .green
            isRightBoxPressed = true
        } else {
            rightBox.color = .black
            isRightBoxPressed = false
        }
    }
    
    func touchUp(atPoint pos : CGPoint) {
        // 无需判断手指位置,只要按钮曾被按下就恢复原色
        if isRightBoxPressed {
            rightBox.color = .black
            isRightBoxPressed = false
        }
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches { self.touchDown(atPoint: t.location(in: self)) }
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches { self.touchUp(atPoint: t.location(in: self)) }
    }
    
    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches { self.touchUp(atPoint: t.location(in: self)) }
    }
    
    override func update(_ currentTime: TimeInterval) {
        // Called before each frame is rendered
    }
}

关键修改点

  • 新增isRightBoxPressed变量,专门跟踪按钮的按下状态
  • touchDown时标记按钮为按下状态
  • touchMoved时根据触摸位置更新状态与颜色
  • touchUp时直接依据之前的按下状态恢复颜色并重置状态

此修改后,无论手指是快速滑动离开还是正常抬起,按钮都会正确恢复原色。

内容的提问来源于stack exchange,提问作者Chris Tucker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 14:39:53