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

Swift中圆形视图Tap Gesture无效,如何实现点击计分?

问题:圆形Tap Gesture无法触发,请求修复并实现计分功能

我正在开发一款单页游戏,玩家点击圆形即可提升分数等级。游戏已接近完成,但圆形上的Tap Gesture无法触发。我尝试了以下代码但没有效果,请帮忙检查代码并告知如何让Tap Gesture生效并实现计分功能,若我有错误请指正。

import UIKit
import AVFoundation

class Demogame: UIViewController {

    @IBOutlet weak var scoreLabel: UILabel!

    var score = 0
    var isGameOver = false

    override func viewDidLoad() {
        super.viewDidLoad()
        startGame()
    }

    func startGame() {
        score = 0
        scoreLabel.text = "Score: \(score)"
        isGameOver = false

        // 创建生成圆形的计时器
        Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true) { timer in
            if !self.isGameOver {
                self.spawnCircle()
            } else {
                timer.invalidate()
            }
        }
    }

    func spawnCircle() {
        let circleSize = CGSize(width: 50, height: 50)
        let circleView = UIView(frame: CGRect(origin: CGPoint(x: CGFloat.random(in: 50...view.frame.width - circleSize.width - 50),
                                                              y: CGFloat.random(in: 100...view.frame.height - circleSize.height - 50)),
                                              size: circleSize))

        circleView.backgroundColor = UIColor.random()
        circleView.layer.cornerRadius = circleSize.width / 2
        view.addSubview(circleView)

        // 为每个圆形添加点击手势识别器
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
        circleView.addGestureRecognizer(tapGesture)

        // 圆形出现和消失的动画
        UIView.animate(withDuration: 3.0, animations: {
            circleView.alpha = 0.0
        }) { (completed) in
            if completed {
                circleView.removeFromSuperview()
            }
        }
    }

    @objc func handleTap(_ sender: UITapGestureRecognizer) {
        if isGameOver {
            return
        }

        if let tappedView = sender.view {
            tappedView.removeFromSuperview()
            score += 1
            scoreLabel.text = "Score: \(score)"
        }
    }
}

extension UIColor {
    static func random() -> UIColor {
        return UIColor(
            red: CGFloat.random(in: 0.0...1.0),
            green: CGFloat.random(in: 0.0...1.0),
            blue: CGFloat.random(in: 0.0...1.0),
            alpha: 1.0
        )
    }
}
问题分析与修复方案

1. 核心问题:UIView默认关闭用户交互

你的代码中Tap Gesture无法触发的根本原因是:UIView的isUserInteractionEnabled属性默认值为false,这会导致所有手势识别器无法响应。

修复方法:在spawnCircle()方法中创建circleView后,添加一行代码开启交互:

circleView.isUserInteractionEnabled = true

2. 优化动画的交互体验

当前动画直接将圆形的alpha从默认值(0)变到0,会导致圆形刚生成就处于透明状态,用户难以点击。可以调整为:

// 先让圆形完全显示
circleView.alpha = 1.0
// 再执行消失动画
UIView.animate(withDuration: 3.0, animations: {
    circleView.alpha = 0.0
}) { (completed) in
    if completed {
        circleView.removeFromSuperview()
    }
}

这样能保证圆形在可见的3秒内都能正常响应点击。

3. 可选优化:避免计时器循环引用

当前的闭包计时器存在潜在的循环引用风险,建议将计时器保存为实例变量并使用弱引用:

// 新增实例变量
var spawnTimer: Timer?

func startGame() {
    score = 0
    scoreLabel.text = "Score: \(score)"
    isGameOver = false
    
    // 先取消之前的计时器,避免重复创建
    spawnTimer?.invalidate()
    spawnTimer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true) { [weak self] timer in
        guard let self = self, !self.isGameOver else {
            timer.invalidate()
            return
        }
        self.spawnCircle()
    }
}

4. 计分功能验证

修复上述问题后,handleTap(_:)方法会正常触发,每次点击圆形时:

  • 圆形会被移除
  • 分数自动+1
  • 分数标签会实时更新显示

内容的提问来源于stack exchange,提问作者Sham Dhiman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 00:45:59