简单的 MVC 计时器- Swift

Simple MVC Timer- Swift

我知道这是一个非常基本的问题,我正在尝试重构我的代码 atm 并且 运行 遇到了计时器问题。我想做的只是让一个简单的倒数计时器打印到控制台

这是我现在的代码片段

VC------

var seconds = 60

override func viewDidLoad() {
    super.viewDidLoad()
    self.modelInstance.gameTimerMethod(timeParam: self.seconds)     
}

型号-----

func gameTimerMethod(timeParam : Int)  {
    gameTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(decreaseGameTimer(secondsParam:)), userInfo: timeParam, repeats: true)
    print (timeParam)
}

func decreaseGameTimer(secondsParam: Int) {
    var printNumber = secondsParam
    printNumber -= 1
    print (printNumber)
}

理想情况下,我希望它在控制台中执行的操作只是暂时从 60 开始以每秒一个数字的速度倒计时。虽然控制台以每秒一个数字的速度记录,但出于某种原因,它会重复记录数字 105553117734207,而不是 60 秒倒计时。

谢谢!

printNumber设为class变量,而不是放在方法中,这样定时器每次调用时都不会重置

同样在 gameTimerMethod 中,在调用计时器之前将 printNumber 设置为 timeParam

您的模型将类似于以下内容:

class YourModel {
    var printNumber = 0

    func gameTimerMethod(timeParam : Int)  {

        printNumber = timeParam
        gameTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(decreaseGameTimer(), userInfo: nil, repeats: true)
        print (timeParam)
    }

    func decreaseGameTimer() {
        printNumber -= 1
        print (printNumber)
    }
}

传递给 decreaseGameTimer 的值是 Timer 实例。它有一个 属性 userInfo 引用传递给 Timer 构造函数的对象。

创建一个 class 来保存你的计数,然后将那个 class 的实例传递给计时器的 userInfo:

class Model {

    class TimerInfo {
        var count: Int

        // Pointer to function or closure to call when value changes
        var callback: ((Int) -> Void)?

        init(start: Int, callback: @escaping (Int) -> Void) {
            count = start
            self.callback = callback
        }

        deinit {
            print("TimerInfo deinit")
        }
    }

    @objc func decreaseGameTimer(_ timer: Timer) {
        if let userInfo = timer.userInfo as? TimerInfo {
            userInfo.count -= 1

            // call callback with new value
            userInfo.callback?(userInfo.count)

            print(userInfo.count)
            if userInfo.count == 0 {
                print("done")
                timer.invalidate()
            }
        }
    }

    func gameTimerMethod(timeParam: Int, callback: @escaping (Int) -> Void) {
        _ = Timer.scheduledTimer(timeInterval: 1, target: self,
                                 selector: #selector(decreaseGameTimer),
                                 userInfo: TimerInfo(start: timeParam, callback: callback),
                                 repeats: true)
    }
}

那么你可以这样称呼它:

override func viewDidLoad() {
    super.viewDidLoad()

    // The closure that follows the gameTimerMethod call is using trailing
    // closure syntax.  It gets passed to gameTimerMethod as the second
    // parameter named callback.  This closure will get called every
    // second until the timer finishes.

    self.modelInstance.gameTimerMethod(timeParam: self.seconds) { value in
        self.label.text = "\(value)"
    } 

    // Just for fun, lets run a second one at the same time
    self.modelInstance.gameTimerMethod(timeParam: 10) { value in
        self.label2.text = "\(value)"
    }   
}