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

Swift中UICollectionView内UIProgressView选中后不更新问题求助

嘿,我来帮你排查这个UICollectionView里UIProgressView不更新的问题!你现在的代码里有几个关键问题导致了这个现象,咱们一步步来解决:

核心问题与修复方案

1. 错误的Cell获取逻辑

你在didSelectItemAt方法里用了dequeueReusableCell(withReuseIdentifier:for:)——这个方法是从复用队列里取出一个新的/可重用的Cell,根本不是用户当前选中的、正在屏幕上显示的那个Cell!所以你更新的是一个看不见的Cell,自然看不到进度变化。

正确的做法是用collectionView.cellForItem(at: indexPath)获取当前显示的目标Cell:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    // 确保能获取到当前显示的选中Cell
    guard let cell = collectionView.cellForItem(at: indexPath) as? MyCell else {
        return
    }
    // 后续的Timer逻辑写在这里
}

2. Timer的循环引用与生命周期管理

直接创建Timer容易出现两个问题:一是循环引用导致内存泄漏,二是Cell被复用时旧Timer还在跑,会干扰其他Cell的进度。咱们需要优化Timer的创建方式,并在Cell复用的时候清理Timer。

优化后的完整Timer代码

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    guard let cell = collectionView.cellForItem(at: indexPath) as? MyCell else {
        return
    }
    
    // 先停止Cell上可能存在的旧Timer,避免重复触发
    cell.timer?.invalidate()
    
    // 创建Timer时用weak引用Cell,避免循环引用
    let timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak cell] timer in
        guard let targetCell = cell else {
            // 如果Cell已经被释放,立刻停止Timer
            timer.invalidate()
            return
        }
        
        let newProgress = targetCell.progress.progress + 0.1
        // 处理进度超过100%的情况
        if newProgress >= 1.0 {
            targetCell.progress.setProgress(1.0, animated: true)
            timer.invalidate()
        } else {
            targetCell.progress.setProgress(newProgress, animated: true)
        }
    }
    
    // 将Timer存到Cell的属性中,方便后续复用的时候清理
    cell.timer = timer
}

3. 给MyCell添加Timer属性并处理复用逻辑

你需要在自定义Cell类里添加一个Timer属性,并重写prepareForReuse方法,在Cell被复用前停止Timer、重置进度:

class MyCell: UICollectionViewCell {
    @IBOutlet weak var progress: UIProgressView!
    // 用来保存当前Cell的Timer
    var timer: Timer?
    
    override func prepareForReuse() {
        super.prepareForReuse()
        // 停止Timer并置空
        timer?.invalidate()
        timer = nil
        // 重置进度条
        progress.setProgress(0.0, animated: false)
    }
}

这样调整之后,选中Cell时就能正确更新对应的UIProgressView,同时还能避免Cell复用带来的各种异常问题。

内容的提问来源于stack exchange,提问作者Dimoreno

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:33:10