后台计时器的事件处理程序未启动

时间:2019-10-21 08:54:22

标签: swift

我正在尝试创建带有倒数计时器的应用。 UI已设置并正确连接到代码。我正在使用一个自定义类来表示类型为DispatchSourceTimer的后台计时器成员的计时器。

我的问题是,本应触发的事件没有触发-关于为什么的任何提示都受到高度赞赏...到目前为止找不到解决方案。

我的目标是通过KVO用剩余时间更新标签,但是到目前为止,由于计时器似乎现在没有被触发,因此KVO当然不会做任何事情。

这是我的View Controller:

import UIKit

class MainViewController: UIViewController {
    //MARK: - Properties
    var currentTimer = PomTimer()

    //MARK: - Outlets
    @IBOutlet weak var startStopBtn: UIButton!
    @IBOutlet weak var countdownLabel: UILabel!

    //MARK: - View Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()

        countdownLabel.text = currentTimer.description

        currentTimer.addObserver(self, forKeyPath: #keyPath(PomTimer.timeLeft), options: .new, context: nil)
    }

    //MARK: - Button Actions

    @IBAction func startStopBtnTapped(_ sender: UIButton) {
        if currentTimer.state == .suspended {
            currentTimer.resume()
            startStopBtn.setImage(UIImage(systemName: "stop.circle.fill"), for: .normal)
        } else {
            currentTimer.suspend()
            startStopBtn.setImage(UIImage(systemName: "play.circle.fill"), for: .normal)
        }
    }

    @IBAction func resetBtnTapped(_ sender: UIButton) {
    }

    //MARK: - KVO Observer Method
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "timeLeft" {
            countdownLabel.text = currentTimer.timeLeft.description
        }
    }
}

这是我的自定义计时器类:

import Foundation

class PomTimer: NSObject {
    //MARK: - Properties
    private let uuid = UUID()
    private let timerDueTimestamp = Date().addingTimeInterval(25 * 60.0)

    @objc var timeLeft: TimeInterval = 25 * 60

    //MARK: - Background Timer Logic
    lazy var timer: DispatchSourceTimer = {
        let t = DispatchSource.makeTimerSource()
        t.schedule(deadline: .now() + self.timeLeft, repeating: 1.0)
        t.setEventHandler(handler: { [weak self] in
            self?.timeLeft -= 1.0
        })
        return t
    }()

    enum State {
        case suspended, resumed
    }

    var state: State = .suspended

    //MARK: - Custom String
    override var description: String {
        let f = DateComponentsFormatter()
        f.unitsStyle = .positional
        f.allowedUnits = [.minute, .second]
        f.zeroFormattingBehavior = .pad
        return f.string(from: timeLeft)!
    }

    //MARK: - Functions
    func resume() {
        if state == .resumed {
            return
        }
        state = .resumed
        timer.activate()
    }

    func suspend() {
        if state == .suspended {
            return
        }
        state = .suspended
        timer.suspend()
    }

    //MARK: - Object Lifecycle
    deinit {
        timer.setEventHandler {}
        timer.cancel()
        resume()
    }
}

0 个答案:

没有答案