Swift:如何使用计时器每秒(或更短)更新标签?

时间:2017-08-10 17:56:09

标签: ios timer sprite-kit

我在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()
    }

 updateScore() {
     scoreLabel.text = "\(score)"
 }

加载GameScene时,计时器在didMove()中启动。

我尝试每0.5秒调用一次countUp()。在此函数中,变量秒数增加并且舍入加上得分变量增加。从那里我想调用updateScore函数来更新scoreLabel.text - 但这不起作用。该函数被调用,但scoreLabel没有更新,虽然当我尝试打印得分变量时,它表明它不断增加。

我怎样才能实现这一点以及这里有什么问题?

2 个答案:

答案 0 :(得分:3)

除非您使用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并将计时器操作附加到节点而不是场景。然后,当您需要暂停计时器时,您可以暂停该节点。这样可以在您的计时器暂停时继续更新场景。

答案 1 :(得分: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() 
    }
}