Как зафиксировать прошедшее время, когда таймер приостановлен - PullRequest
1 голос
/ 23 октября 2019

Я собрал таймер обратного отсчета, чтобы пользователь мог записывать свои тренировочные сезоны. У меня это работает нормально, за исключением одной части. Пользователь может приостановить сеанс. Пока проблема с кодом заключается в том, что код таймера останавливается, но время продолжает работать.

Например, если пользователь устанавливает таймер на 5 минут и нажимает кнопку запуска, то на полпути пользователь нажимает паузы и ждет 2 минуты (что означает, что истекшее время теперь составляет 7 минут). когда таймер заканчивается 7 минут вместо 5 минут. Если пользователь отменяет сеанс, это нормально, но только потому, что я устанавливаю жесткое время начала и окончания.

Мой вопрос состоит в том, как мне записать время тренировки, если пользователь приостановил таймер?

Вот объяснение пользовательского интерфейса: timerLabel содержит время работы. MinLabel показывает количество минут, в течение которыхПользователь установил таймер на «ClockLabel» показывает количество часов, которые пользователь установил на таймер. Есть два ползунка. Один для установки минут и один для установки часов Есть также две кнопки. A Кнопка Play / Cancel и кнопка Pause / Resume

Заранее спасибо!

import UIKit
import AVFoundation

class Practice_Timmer_VC: UIViewController
{
    @IBOutlet weak var navBar: UINavigationItem!
    @IBOutlet weak var viewLabel: DesignableLabel!
    @IBOutlet weak var timerLabel: DesignableLabel!
    @IBOutlet weak var theTabbar: UITabBar!
    @IBOutlet weak var minutesLabel: UILabel!
    @IBOutlet weak var hoursLabel: UILabel!

    var seconds: Int  = 60
    var timer = Timer()
    var isTimerRunning: Bool = false
    var resumeTapped: Bool  = false
    var theTime: String = ""

    var startTime: Date = Date()
    var endTime: Date = Date()

    var total: Int = 0

    var chimeSoundEffect: AVAudioPlayer?

    override func viewDidLoad()
    {
        super.viewDidLoad()

        theTabbar.selectedItem = theTabbar.items![4]

        view.backgroundColor = UIColor(patternImage: UIImage(named: "Carbon.png")!)

        startButton.isEnabled = true
        pauseButton.isEnabled = false

        populateTheTimer()

    }// End of viewDidLoad

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(true)

        startButton.setImage(UIImage(named: "Play"), for: .normal)
    }

    func populateTheTimer()
    {
        let theName = ModelData.getTheTrickName()
        navBar.title = theName
    }

    func getTheDifference(start: Date, end: Date)
    {
        let theFormatter = DateComponentsFormatter()
        theFormatter.allowedUnits = [.hour, .minute]
        theFormatter.unitsStyle = .full

        theTime = theFormatter.string(from: start, to: end) ?? ""
    }

    func formattedDate() -> String
    {
        let formatter = DateFormatter()
        let date = Date()
        formatter.locale = Locale.current
        formatter.dateStyle = .medium
        return formatter.string(from: date)
    }

    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)
    }

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

        isTimerRunning = true
        pauseButton.isEnabled = true
    }

    @objc func updateTimer()
    {
        if seconds < 1
        {
            timer.invalidate()

            endTime = Date()

            getTheDifference(start: startTime, end: endTime)

            startButton.setImage(UIImage(named: "Play"), for: .normal)
            startButton.isEnabled = true
            pauseButton.isEnabled = false

            playTheSound()
            showAlert()

        } else {
            seconds -= 1
            timerLabel.text = timeString(time: TimeInterval(seconds))
        }
    }

    func showAlert()
    {
        let theAlert = UIAlertController(title: "Practice Ended", message: "\(formattedDate())\nPracticed for: \(theTime)", preferredStyle: .alert)

        let saveTheInfo = UIAlertAction(title: "Save Practice", style: .default) { (saveAction) in
            self.gotoAddEdit()
        }

        let cancel = UIAlertAction(title: "Cancel", style: .cancel) { (cancelAction) in

        }

        theAlert.addAction(saveTheInfo)
        theAlert.addAction(cancel)

        present(theAlert, animated: true)
    }

    func playTheSound()
    {
        let path = Bundle.main.path(forResource: "chime.mp3", ofType: nil)!
        let theURL = URL(fileURLWithPath: path)

        do {
            chimeSoundEffect = try AVAudioPlayer(contentsOf: theURL)
            chimeSoundEffect?.play()
        } catch {

        }
    }

    func gotoAddEdit()
    {
        let sb = UIStoryboard(name: "Main", bundle: nil)
        if let addEdit = sb.instantiateViewController(withIdentifier: "Practice_Log_VC") as? Practice_Log_VC
        {

            addEdit.passData = "\(formattedDate())\nPracticed for: \(theTime)"
            addEdit.delegate = self as? Timer2PracticeLog_Delegate

            self.navigationController?.pushViewController(addEdit, animated: ModelData.isAnimation())
            self.navigationController?.view.semanticContentAttribute = .forceLeftToRight
        }
    }

    @IBOutlet weak var startButton: DesignableButton!
    @IBAction func startButtonTapped(_ sender: DesignableButton)
    {
        let minutes2Seconds = Int(minutesSliderOutlet.value) * 60
        let hours2Seconds = Int(hoursSliderOutlet.value) * 3600

        seconds = Int(minutes2Seconds + hours2Seconds)

        if isTimerRunning == false // Start
        {
            if seconds > 0
            {
                startTime = Date()

                sender.setImage(UIImage(named: "Cancel_Video"), for: .normal)
                runTimer()

            } else {
                view.sendConfirmationAlert(theTitle: "Error! Practice time is set to 0.", theMessage: "Please set the practice time.", buttonTitle: "OK")
                minutesSliderOutlet.value = 1
                minutesLabel.text = "1 Minute"
            }

        } else { // Cancel

            endTime = Date()

            timer.invalidate()

            seconds = 0

            getTheDifference(start: startTime, end: endTime)

            sender.setImage(UIImage(named: "Play"), for: .normal)

            minutesSliderOutlet.value = 1
            minutesLabel.text = "1 Minute"
            hoursSliderOutlet.value = 0
            hoursLabel.text = "0 Hours"

            timerLabel.text = timeString(time: TimeInterval(seconds))
            isTimerRunning = false
            pauseButton.isEnabled = false

            showAlert()
        }
    }

    @IBOutlet weak var pauseButton: DesignableButton!
    @IBAction func pauseButtonTapped(_ sender: DesignableButton)
    {
        if resumeTapped == false
        {
            timer.invalidate()
            resumeTapped = true
            sender.setImage(UIImage(named: "Resume"), for: .normal)

        } else {
            runTimer()
            resumeTapped = false
            sender.setImage(UIImage(named: "Pause"), for: .normal)
        }
    }

    @IBOutlet weak var minutesSliderOutlet: UISlider!
    @IBAction func minuteSlider(_ sender: UISlider)
    {
        let minutes = Int(sender.value)
        if minutes > 1
        {
            minutesLabel.text = String(minutes) + " Minutes"
        } else {
            minutesLabel.text = String(minutes) + " Minute"
        }
    }

    @IBOutlet weak var hoursSliderOutlet: UISlider!
    @IBAction func hoursSlider(_ sender: UISlider)
    {
        let hours = Int(sender.value)
        if hours > 1
        {
            hoursLabel.text = String(hours) + " Hours"
        } else {
            hoursLabel.text = String(hours) + " Hour"
        }
    }

}// End of Class

1 Ответ

0 голосов
/ 23 октября 2019

Получите время, когда пользователь приостанавливает приложение как новую дату (), а также время, когда пользователь возобновляет приложение. Получите разницу между этими двумя датами / временем и вычтите ее из общего времени, чтобы получить правильное общее время для тренировки.

Например, у вас может быть переменная, которая отслеживает общее время паузы:

var totalPauseTime: TimeInterval = 0
var pauseStartTime: Date?

Он пересчитывается каждый раз, когда пользователь нажимает кнопку паузы, чтобы возобновить (предварительно нажав ее для паузы):

@IBAction func pauseButtonTapped(_ sender: DesignableButton)
    {
        if resumeTapped == false
        {
            pauseStartTime = Date() 
            timer.invalidate()
            resumeTapped = true
            sender.setImage(UIImage(named: "Resume"), for: .normal)

        } else {
            if let pauseStartTime = pauseStartTime {
                totalPauseTime += Date().timeIntervalSinceReferenceDate - pauseStartTime.timeIntervalSinceReferenceDate
            }
            runTimer()

            resumeTapped = false
            sender.setImage(UIImage(named: "Pause"), for: .normal)
        }
    }

На самом деле не проверял вышеуказанный код, но ондолжен дать идею. Затем вы вычитаете totalPauseTime в той точке кода, где вы рассчитываете общее время сеанса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...