You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 02:05:23