簡體   English   中英

等待 Swift 定時器完成

[英]Wait for Swift timers to finish

所以我在 swift 5 上做一個簡單的游戲,我基本上有一個 3..2..1.. go 計時器來開始游戲,然后是 3..2..1..stop 計時器來停止游戲。 最后是顯示分數的 function。 對於每個 function 調用,我需要一種方法來等待計時器在下一個開始之前完成,有什么建議嗎? 到目前為止,這是我的代碼。 (此外,如果您對應用程序有任何其他建議,請告訴我,最終目標是記錄您在 3 秒內可以點擊按鈕的次數)

var seconds = 3 //Starting seconds
var countDownTimer = Timer()
var gameTimer = Timer()
var numberOfTaps = 0

override func viewDidLoad() {
    super.viewDidLoad()

    self.startCountdown(seconds: seconds)
    self.gameCountdown(seconds: seconds)
    self.displayFinalScore()


}

func startCountdown(seconds: Int) {
        countDownTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] timer in
            self?.seconds -= 1
            if self?.seconds == 0 {
                self?.countdownLabel.text = "Go!"
                timer.invalidate()
            } else if let seconds = self?.seconds {
                self?.countdownLabel.text = "\(seconds)"
            }
        }
}

func gameCountdown(seconds: Int) {
        gameTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] timer in
              self?.seconds -= 1
              if self?.seconds == 0 {
                  self?.countdownLabel.text = "Stop!"
                  timer.invalidate()
              } else if let seconds = self?.seconds {
                  self?.countdownLabel.text = "\(seconds)"
              }
          }
  }


    deinit {
        // ViewController going away.  Kill the timer.
        countDownTimer.invalidate()
    }




@IBOutlet weak var countdownLabel: UILabel!


@IBAction func tapMeButtonPressed(_ sender: UIButton) {
    if gameTimer.isValid {
        numberOfTaps += 1
    }
}

func displayFinalScore() {
    if !gameTimer.isValid && !countDownTimer.isValid {
        countdownLabel.text = "\(numberOfTaps)"
    }
}

方法不應該是 function 調用等待定時器完成,而是定時器應該在完成時調用函數。

因此,您需要將 function 調用移出viewDidLoad並將它們放入Timer塊中。

self.gameCountdown(seconds: seconds)
self.displayFinalScore() 

即 function 調用self.gameCountdown(seconds: seconds)將 go 在startCountdown開始的計時器塊內。 在這種情況下,當您在秒變為 0 時使計時器無效時,您調用gameCountdown

同樣,在gameCountdown啟動的計時器中,當秒數變為 0 時調用self.displayFinalScore

很少有其他建議。 您應該避免檢查tapMeButtonPressed中的屬性。 您應該禁用並啟用點擊我按鈕。 即在開始游戲倒計時時啟用它,並在結束時禁用它。

同樣,您不需要檢查displayFinalScore中計時器的 state 。 它應該只做一件事,即顯示最終分數。

以后會為您省去很多麻煩:)。 我的 2 美分。

您應該考慮您的游戲可能處於的狀態。它可能是 -

  • setup - 建立游戲
  • 開始- 前三秒
  • running - 在前三秒之后但在結束之前
  • 結局——在最后三秒
  • 結束- 時間到了。

每次您的計時器滴答作響時,您都需要考慮您需要采取什么行動以及您需要移動到什么 state。 您還沒有說您希望游戲持續多長時間,但假設是 30 秒。

當一個新游戲開始時,你在setup state; 該按鈕被禁用(即它不會對點擊做出反應)並且您將分數設置為 0。您移動到starting state。 starting時,您會顯示倒計時。 三秒鍾后,您啟用按鈕並進入running的 state。 達到 27 秒后,您將進入ending state 並顯示結束倒計時 最后時間到了,您進入ended state,禁用按鈕並顯示分數。

你可以這樣編碼


enum GameState {

    case setup
    case starting
    case running
    case ending
    case ended
}

class ViewController: UIViewController {

    @IBOutlet weak var startButton: UIButton!
    @IBOutlet weak var tapButton: UIButton!
    @IBOutlet weak var countdownLabel: UILabel!

    var gameState = GameState.ended
    var gameTimer:Timer?
    var numberOfTaps = 0
    var gameStartTime = Date.distantPast
    let GAMEDURATION: TimeInterval = 30

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBAction func startButtonTapped(_ sender: UIButton) {
        self.startGame()
    }

    @IBAction func tapMeButtonPressed(_ sender: UIButton) {
        self.numberOfTaps += 1
    }

    func startGame() {
        self.gameState = .setup

        self.gameTimer = Timer.scheduledTimer(withTimeInterval:0.1, repeats: true) { timer in

            let elapsedTime = -self.gameStartTime.timeIntervalSinceNow
            let timeRemaining = self.GAMEDURATION-elapsedTime
            switch self.gameState {
            case .setup:
                self.gameStartTime = Date()
                self.tapButton.isEnabled = false
                self.startButton.isEnabled = false
                self.numberOfTaps = 0
                self.gameState = .starting
            case .starting:
                if elapsedTime > 2.5 {
                    self.gameState = .running
                    self.tapButton.isEnabled = true
                    self.countdownLabel.text  = "Go!"
                } else {
                    let countdown = Int(3-round(elapsedTime))
                    self.countdownLabel.text = "\(countdown)"
                }
            case .running:
                if timeRemaining < 4 {
                    self.gameState = .ending
                }
            case .ending:
                let countdown = Int(timeRemaining)
                self.countdownLabel.text = "\(countdown)"
                if timeRemaining < 1 {
                    self.countdownLabel.text = "Stop"
                    self.gameState = .ended
                    self.tapButton.isEnabled = false
                }
            case .ended:
                if timeRemaining <= 0 {
                    self.countdownLabel.text = "You tapped the button \(self.numberOfTaps) times"
                    self.startButton.isEnabled = true
                    self.gameTimer?.invalidate()
                    self.gameTimer = nil
                }
            }
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM