Swift:如何使用计时器每秒(或更短)更新标签?
Posted
技术标签:
【中文标题】Swift:如何使用计时器每秒(或更短)更新标签?【英文标题】:Swift: How to update a label every second (or shorter) with a timer? 【发布时间】:2017-08-10 17:56:08 【问题描述】:我在 Xcode 中为游戏 (SpriteKit) 创建了一个简单的计时器:
变量 timer、seconds 和 score 在类中初始化。
func scoreTimer()
timer = Timer.scheduledTimer(timeInterval: 0.05, target: self, selector: #selector(countUp), userInfo: nil, repeats: true)
@objc func countUp()
seconds += 0.05
seconds = (seconds * 100).rounded() / 100
score = score + 0.015
updateScore()
func updateScore()
scoreLabel.text = "\(score)"
当 GameScene 被加载时,定时器在 didMove() 中启动。
我尝试每 0.5 秒调用一次 countUp()。在这个函数中,变量 seconds 增加并四舍五入加上 score 变量增加。从那里我想调用 updateScore 函数来更新 scoreLabel.text - 但这不起作用。调用了函数,但是 scoreLabel 没有更新,虽然当我尝试打印 score 变量时,它显示它在不断增加。
我怎样才能做到这一点,这里有什么问题?
【问题讨论】:
在 updateScore 方法中打印分数? 只是注意到 0.05 != 0.5。 :) 【参考方案1】:除非您使用 SpriteKit 之外的技术,否则应避免使用 SpriteKit 使用计时器。原因是因为 SpriteKit 有自己的时间管理,一个定时器可能不会与之重合。例如,在您的情况下,计时器更新分数。如果你暂停游戏怎么办?除非您记得停止计时器,否则您的计时器仍会增加分数。
相反,依靠行动来做你需要的事情 下面是你如何做你正在寻找的事情。
let wait = SKAction.wait(forDuration: 0.5)
let update = SKAction.run(
seconds += 0.05
seconds = (seconds * 100).rounded() / 100
score = score + 0.015
updateScore()
)
let seq = SKAction.sequence([wait,update])
let repeat = SKAction.repeatForever(seq)
run(repeat)
@RonMyschuk 提到了我错过的一个想法,所以我也会将它添加到我的答案中。
如果您需要创建可以单独暂停或在组中暂停的计时器,则添加额外的 SKNode 并将计时器操作附加到节点而不是场景。然后当你需要暂停计时器时,你可以暂停节点。这将允许您的场景更新在您的计时器暂停时继续。
【讨论】:
我可以有多个并行运行吗?例如,一个 SKAction 每 0.5 秒更新一次分数,一个 Action 每 30 秒播放一次随机函数,那么仅使用一个 SKAction 会以不同的方式完成吗? 是的,只要你不为同一个键分配 2 个动作,它们将并行运行,除非你特别把它放在一个序列中 谢谢。我是否将其放入“覆盖函数更新(_ currentTime:TimeInterval)” - 如果是这样,使用什么 TimeInterval? 不,你只在需要的时候调用它一次,把它放在更新中会在每个循环中添加一个新的计时器 谢谢,一切都很好。我想当 GameScene 发生变化(即 GameOverScene 或回到 MenuScene)时,由于更新功能,计时器会自动停止,我不必停止或重置它?【参考方案2】:我赞同在 Spritekit 中应该避免使用 Timers 的声明。
您还可以使用更新循环更新您的标签。
通过更新循环控制时间允许您在游戏停止时暂停“计时器”,而无需从场景中移除动作。
您还可以使用此方法运行多个计时器
private var updateTime: Double = 0
private var updateTime2: Double = 0
override func update(_ currentTime: CFTimeInterval)
//this will be some sort of variable dictating the state of your game
guard gameState == .playing else
updateTime = 0
updateTime2 = 0
return
if updateTime == 0
updateTime = currentTime
if updateTime2 == 0
updateTime2 = currentTime
if currentTime - updateTime > 0.5
//do something every half second
updateTime = currentTime
score = score + 0.015
updateScore()
if currentTime - updateTime2 > 30
//do something every 30 seconds
updateTime2 = currentTime
someFunc()
【讨论】:
我有点困惑你所说的“如果游戏停止,则暂停“计时器”,而不必从场景中删除动作。”如果场景暂停,那么您的动作也会暂停。 并非所有游戏中的停止都必须通过暂停场景来处理。这种设置方式将决定计时器将针对哪些游戏状态进行计时,以及计时器不会计时的任何其他游戏状态。我个人喜欢使用这种方法,即使我暂停游戏也不暂停场景,因为暂停场景不允许我像暂停菜单中的幻灯片那样执行 SKActions。 啊,好吧,这就是为什么我总是推荐使用 worldNode,它允许您将游戏的行为与场景中可能存在的其他元素分开 我也是这样做的(我使用gameLayer作为我的主节点),我没有在我的回答中涉及到,因为我真的不想让OP太复杂 我明白了,只是想明白你说的游戏停止是什么意思,你的意思是如果游戏处于暂停状态,我还以为你指的是切换应用程序以上是关于Swift:如何使用计时器每秒(或更短)更新标签?的主要内容,如果未能解决你的问题,请参考以下文章