iOS Swift计时器如何实现倒计时进度条(时间耗尽时填满)
实现iOS计时器进度条(时间耗尽时填满)
你的需求是给现有计时器添加进度条,要求时间耗尽时进度条完全填满。以下是具体实现步骤和修改后的代码:
关键思路
进度条的核心逻辑是已流逝时间占总剩余时间的比例:
- 初始状态(刚设置计时器):已流逝时间为0,进度条进度为0
- 时间流逝时:已流逝时间增加,进度条进度逐步提升
- 时间耗尽时:已流逝时间等于总剩余时间,进度条进度为1(完全填满)
具体修改步骤
1. 恢复进度条的IBOutlet连接
取消注释ProgressBar的IBOutlet,并修正变量名符合Swift命名规范:
@IBOutlet var progressBar: UIProgressView! @IBOutlet var label: UILabel!
2. 添加必要的变量
新增两个变量:存储总剩余秒数(用于计算进度)、持有计时器实例(避免重复创建多个计时器):
var hours: Int = 0 var mins: Int = 0 var secs: Int = 0 var totalSeconds: Int = 0 // 存储计时器的总剩余秒数 var countdownTimer: Timer? // 持有计时器实例,方便后续停止
3. 初始化进度条
在viewDidLoad中设置进度条初始进度为0:
override func viewDidLoad() { super.viewDidLoad() progressBar.progress = 0.0 }
4. 计算总剩余秒数并初始化进度
在didCreateEvent方法中,新增存储总秒数的逻辑,并调用进度更新方法:
private func didCreateEvent(name: String, targetDate: Date){ self.title = name let difference = floor(targetDate.timeIntervalSince(Date())) if difference > 0.0 { totalSeconds = Int(difference) // 存储总剩余秒数 // 简化剩余时间计算 let computedHours: Int = totalSeconds / 3600 let remainder: Int = totalSeconds % 3600 let minutes: Int = remainder / 60 let seconds: Int = remainder % 60 print("\(computedHours) \(minutes) \(seconds)") hours = computedHours mins = minutes secs = seconds updateLabel() updateProgress() // 初始化进度条 startTimer() } else{ print("negative interval") } }
5. 修改计时器逻辑,添加进度更新
更新startTimer方法,处理计时器的重复创建问题,并在每次时间更新后同步更新进度条:
private func startTimer() { // 先停止之前的计时器,避免多个计时器同时运行 countdownTimer?.invalidate() countdownTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in guard let self = self else { return } if self.secs > 0 { self.secs -= 1 } else if self.mins > 0 { self.mins -= 1 self.secs = 59 } else if self.hours > 0 { self.hours -= 1 self.mins = 59 self.secs = 59 } else { // 时间耗尽,停止计时器 self.countdownTimer?.invalidate() self.countdownTimer = nil } self.updateLabel() self.updateProgress() // 每次时间更新后同步进度条 } }
6. 新增进度条更新方法
创建专门的方法计算并更新进度条:
private func updateProgress() { guard totalSeconds > 0 else { progressBar.progress = 1.0 // 总秒数为0时直接填满进度条 return } // 计算当前剩余秒数 let remainingSeconds = hours * 3600 + mins * 60 + secs // 计算进度:已流逝时间 / 总时间 let progress = Float(totalSeconds - remainingSeconds) / Float(totalSeconds) progressBar.progress = progress }
完整修改后的代码
import UIKit class ViewController: UIViewController { @IBOutlet var progressBar: UIProgressView! @IBOutlet var label: UILabel! var hours: Int = 0 var mins: Int = 0 var secs: Int = 0 var totalSeconds: Int = 0 var countdownTimer: Timer? override func viewDidLoad() { super.viewDidLoad() progressBar.progress = 0.0 } @IBAction func didTapAddButton() { let vc = storyboard?.instantiateViewController(identifier:"date_picker") as! DateViewController vc.title = "New Event" vc.completionHandler = { [weak self] name, date in DispatchQueue.main.async { self?.didCreateEvent(name: name, targetDate: date) } } navigationController?.pushViewController(vc, animated: true) } private func didCreateEvent(name: String, targetDate: Date){ self.title = name let difference = floor(targetDate.timeIntervalSince(Date())) if difference > 0.0 { totalSeconds = Int(difference) let computedHours: Int = totalSeconds / 3600 let remainder: Int = totalSeconds % 3600 let minutes: Int = remainder / 60 let seconds: Int = remainder % 60 print("\(computedHours) \(minutes) \(seconds)") hours = computedHours mins = minutes secs = seconds updateLabel() updateProgress() startTimer() } else{ print("negative interval") } } private func startTimer() { countdownTimer?.invalidate() countdownTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in guard let self = self else { return } if self.secs > 0 { self.secs -= 1 } else if self.mins > 0 { self.mins -= 1 self.secs = 59 } else if self.hours > 0 { self.hours -= 1 self.mins = 59 self.secs = 59 } else { self.countdownTimer?.invalidate() self.countdownTimer = nil } self.updateLabel() self.updateProgress() } } private func updateLabel() { label.text = "\(hours):\(mins):\(secs)" } private func updateProgress() { guard totalSeconds > 0 else { progressBar.progress = 1.0 return } let remainingSeconds = hours * 3600 + mins * 60 + secs let progress = Float(totalSeconds - remainingSeconds) / Float(totalSeconds) progressBar.progress = progress } }
内容的提问来源于stack exchange,提问作者Felipe
相关产品推荐
相关产品推荐

