我准备了一个倒计时计时器,这样用户就可以重新记录他们的练习季。除了一部分,我让它工作正常。允许用户暂停 session 。到目前为止代码的问题是定时器代码暂停但时间继续运行。
例如,如果用户将定时器设置为 5 分钟并点击开始按钮,则在中途用户点击暂停并等待 2 分钟(这意味着耗时现在为 7 分钟)定时器时显示的练习时间结束是 7 分钟而不是 5 分钟。如果用户取消 session 没关系,但这只是因为我设置了硬开始和结束时间。
我的问题是,如果用户暂停计时器,我该如何捕捉练习时间?
这是对 UI 的解释: timerLabel 包含运行时间 minutesLabel 显示用户设置计时器的分钟数 hoursLabel 显示用户将计时器设置为的小时数 有两个 slider 。一个用于设置分钟,一个用于设置小时 还有两个按钮。播放/取消按钮和暂停/恢复按钮
提前致谢!
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
最佳答案
获取用户暂停应用的时间作为新的date(),以及用户恢复应用的时间。获取这两个日期/时间之间的差异,并从总时间中减去该差异以获得正确的练习总时间。
例如,您可以使用一个变量来跟踪总暂停时间:
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)
}
}
还没有实际测试过上面的代码,但它应该给出了一个想法。然后在代码中计算总 session 时间的地方减去 totalPauseTime。
关于ios - 如何在计时器暂停时捕获耗时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58514984/