当我暂停我的计时器,然后尝试再次启动它,它不会运行

时间:2017-07-26 04:54:17

标签: ios swift timer

我正在Swift 3中构建一个应用程序。当我第一次按下启动时,我的计时器开始,但当我暂停它并尝试再次按下启动时,计时器不会让步。为了给出上下文,从表中选择具有附加时间量的计时器。每次定时器加载时,启动按钮最初都会起作用。

protocol TimerViewControllerDelegate: class {
func viewController(_ controller: ViewController, didFinishEditing item: TaskData)
}

class ViewController: UIViewController, UITextFieldDelegate {

@IBOutlet weak var timerLabel: UILabel!
@IBOutlet weak var pauseButton: UIButton!
@IBOutlet weak var startButton: UIButton!
@IBOutlet weak var timerTaskName: UILabel!
@IBOutlet weak var timerTimeSetting: UILabel!
@IBOutlet weak var progressView: UIProgressView!

weak var delegate: TimerViewControllerDelegate?

var timerTask: TaskData?
var timer: Timer?
var progressViewSpeed: Double = 0.0

@IBAction func cancel(_ sender: Any) {
    timer?.invalidate()
    dismiss(animated: true, completion: nil)
    delegate?.viewController(self, didFinishEditing: timerTask!)
}

@IBAction func startButtonTapped(_ sender: Any) {
    timerTask?.startTime = Date()
    runTimer()
    if timerTask?.isTaskRunning == true {
        runTimer()
        self.startButton.isEnabled = false
        self.pauseButton.isEnabled = true
    } else {
        //retrieve start time and run
        timerTask?.startTime = Date()
        runTimer()
        self.startButton.isEnabled = false
        self.pauseButton.isEnabled = true
    }
}

func runTimer() {
    guard timer == nil else {
        return
    }

    timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(ViewController.updateTimer)), userInfo: nil, repeats: true)
}

@IBAction func pauseButtonTapped(_ sender: UIButton) {
    if timerTask?.isTaskRunning == true {
        timer?.invalidate()
        if let timerTask = timerTask, timerTask.isTaskRunning {

            // Calculate the difference between now and when the timerTask was started
            let difference = Int(Date().timeIntervalSince(timerTask.startTime!))
            timerTask.taskRemaining -= difference
            if timerTask.taskRemaining == 0 {
                // Do something when there's no time remaining on the task?
            }

            timerTask.startTime = nil
        }
    }

    else {

        timerTask?.startTime = Date()
        runTimer()
        self.pauseButton.setTitle("Pause",for: .normal)
    }

    self.startButton.isEnabled = true
    self.pauseButton.isEnabled = false
}

/*
@IBAction func resetButtonTapped(_ sender: Any) {
    timer.invalidate()
    seconds = 60
    self.timerLabel.text = timeString(time: TimeInterval(seconds))
    if self.resumeTapped == true {
        self.resumeTapped = false
        self.pauseButton.setTitle("Pause",for: .normal)
    }
    isTimerRunning = false
    pauseButton.isEnabled = false
    startButton.isEnabled = true
}
*/

func updateTimer() {
    guard let timerTask = timerTask else {
        return
    }

    if timerTask.taskRemaining < 1 {
        timer?.invalidate()
        timer = nil
        //Send alert to indicate "time's up!"
    } else {
        updateTime()
    }
    progressViewSpeed = 1 / Double(timerTask.taskRemaining)
    progressView.progress += Float(progressViewSpeed)
}

func timeString(time:TimeInterval) -> String {
    let hours = Int(time) / 3600
    let minutes = Int(time) / 60 % 60
    let seconds = Int(time) % 60
    return String(format:"%02i:%02i:%02i", hours, minutes, seconds)
}

override func viewDidLoad() {
    super.viewDidLoad()

    guard let timerTask = timerTask else {
        return
    }

    if timerTask.isTaskRunning {
        startButton.isEnabled = false
        pauseButton.isEnabled = true
        runTimer()
    } else {
        startButton.isEnabled = true
        pauseButton.isEnabled = false
    }

    timerTaskName.text = timerTask.task
    updateTime()

    self.progressView.transform = CGAffineTransform.identity.rotated(by: CGFloat.pi / 2).scaledBy(x: 1, y: 150)

}

func updateTime() {
    guard let timerTask = timerTask else {
        return
    }

    if let startTime = timerTask.startTime {
        // Calculate the difference between now and when the timerTask was started
        let difference = Int(Date().timeIntervalSince(startTime))

        if timerTask.taskRemaining == difference {
            // Do something when there's no time remaining on the task
            timer?.invalidate()
            timer = nil
        }

        timerLabel.text = timeString(time: TimeInterval(timerTask.taskRemaining - difference))
    } else {
        timerLabel.text = timeString(time: TimeInterval(timerTask.taskRemaining))
    }

}
}

2 个答案:

答案 0 :(得分:1)

您需要使其无效并重新创建它。 “isPaused”bool跟踪状态

var isPaused = true
var timer: Timer?    
@IBAction func pauseResume(sender: AnyObject) {     
    if isPaused{
        timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(ViewController.updateTimer)), userInfo: nil, repeats: true)
        pauseButton.isHidden = false
        startButton.isHidden = true
        isPaused = false
    } else {

        pauseButton.isHidden = true
        startButton.isHidden = false
        timer.invalidate()
        isPaused = true
    }
    }

答案 1 :(得分:1)

一旦您使NSTimer无效,您就无法再次使用它。您应该创建新对象。

请点击此处查看更多From NSTimer Docs

调用此方法请求从当前运行循环中删除计时器;因此,您应始终从安装计时器的同一线程中调用invalidate方法。使计时器失效会立即禁用它,以使其不再影响运行循环。然后,run循环在invalidate方法返回之前或之后的某个时间点删除并释放计时器。一旦失效,就不能重复使用计时器对象。