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

UIProgressView进度不更新问题求助

UIProgressView进度不更新问题求助

我来帮你分析下问题出在哪,以及怎么修复:

首先,你的代码里有两个核心问题:UI布局缺失和主队列阻塞导致界面无法实时刷新,咱们一个个说:

1. 先解决ProgressView的布局问题

你现在只是把progressView add到alert的view上,但完全没设置约束或者frame,这会导致progressView的位置和大小都不对,甚至可能显示异常(比如你看到的灰色初始状态,很可能是因为控件没正确布局,系统没法正确渲染它的进度)。

先给progressView加上约束,确保它能在alert里正常显示:

// 先关闭自动转换约束,避免和手动约束冲突
progressView.translatesAutoresizingMaskIntoConstraints = false
alertView.view.addSubview(progressView)
// 添加具体约束,让进度条在alert底部左右留边
NSLayoutConstraint.activate([
    progressView.leadingAnchor.constraint(equalTo: alertView.view.leadingAnchor, constant: 20),
    progressView.trailingAnchor.constraint(equalTo: alertView.view.trailingAnchor, constant: -20),
    progressView.bottomAnchor.constraint(equalTo: alertView.view.bottomAnchor, constant: -20),
    progressView.heightAnchor.constraint(equalToConstant: 4)
])

2. 进度条不实时更新的核心原因

你现在把所有进度修改、刷新操作都塞在同一个主队列闭包里同步执行——UIKit的界面更新是依赖RunLoop每一轮循环来渲染的,你一下子把progressView.progress从0→0.5→1.0全改完,系统根本没机会在中间刷新界面,只会直接显示最后一次修改后的状态。而且如果refreshStatData和refreshStatDisplay是耗时操作(比如读取数据、计算统计值),还会直接阻塞主队列,导致整个界面卡住,连alert的动画都出不来。

修复后的完整代码

我们把耗时操作放到后台队列,每完成一步就回到主队列更新进度,给系统留足渲染时间:

override func viewDidLoad()  {
    super.viewDidLoad() // 别忘了调用super!这是UIViewController生命周期的必要操作
    tableView.sectionHeaderHeight = 0
    self.navigationController?.isNavigationBarHidden = true
    self.parent?.dismiss(animated: true, completion: nil)
    
    let alertView = UIAlertController(title: "Please wait", message: "Loading stats...", preferredStyle: .alert)
    let progressView = UIProgressView(progressViewStyle: .default)
    progressView.translatesAutoresizingMaskIntoConstraints = false
    alertView.view.addSubview(progressView)
    // 设置进度条约束
    NSLayoutConstraint.activate([
        progressView.leadingAnchor.constraint(equalTo: alertView.view.leadingAnchor, constant: 20),
        progressView.trailingAnchor.constraint(equalTo: alertView.view.trailingAnchor, constant: -20),
        progressView.bottomAnchor.constraint(equalTo: alertView.view.bottomAnchor, constant: -20),
        progressView.heightAnchor.constraint(equalToConstant: 4)
    ])
    
    present(alertView, animated: true) {
        // present完成后,先初始化进度为0
        progressView.progress = 0.0
        // 把耗时的刷新操作放到后台队列,避免阻塞主队列
        DispatchQueue.global(qos: .userInitiated).async { [weak self] in
            guard let self = self else { return }
            // 第一步:刷新数据(耗时操作放后台)
            self.refreshStatData()
            // 回到主队列更新进度,让系统渲染
            DispatchQueue.main.async {
                progressView.progress = 0.5
            }
            // 第二步:刷新显示逻辑(同样耗时的话也放后台)
            self.refreshStatDisplay()
            // 回到主队列更新进度并结束流程
            DispatchQueue.main.async {
                progressView.progress = 1.0
                // 加个短暂延迟,让用户能看到进度条满的状态再关闭alert
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                    alertView.dismiss(animated: true) {
                        self.tableView.isHidden = false
                    }
                }
            }
        }
    }
}

关键修改点说明:

  • 给progressView补了AutoLayout约束,确保它在alert里位置、大小正确,样式渲染正常
  • 把refreshStatData和refreshStatDisplay放到后台队列执行,避免阻塞主队列导致UI卡住
  • 每完成一个后台任务就回到主队列更新进度,给系统留足时间渲染界面变化
  • 最后加了asyncAfter延迟关闭alert,避免进度条刚到100%就消失,用户看不到完整过程
  • 用[weak self]避免循环引用,这是iOS开发里的好习惯,能防止内存泄漏

这样修改后,你就能看到进度条从0→50%→100%的完整变化过程了~

备注:内容来源于stack exchange,提问作者Marc Murphy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 10:22:56