UITableViewCell内UILabel文本不更新问题咨询
解决UITableViewCell中UILabel无法更新下载百分比的问题
兄弟,我帮你梳理下这个问题的常见原因和解决办法,咱们一步步来排查:
1. 代理回调不在主线程,UI更新无效
AVAssetDownloadTask的代理方法默认是在后台队列执行的,而iOS的UI操作必须在主线程进行。这就是为什么初期可能碰巧在主线程(或者系统刚好调度到主线程),后面切换到后台线程后,UILabel就不更新了。
解决办法很简单,把更新UILabel的代码包在DispatchQueue.main.async里,比如:
func urlSession(_ session: URLSession, assetDownloadTask: AVAssetDownloadTask, didLoad timeRange: CMTimeRange, totalTimeRangesLoaded loadedTimeRanges: [NSValue], timeRangeExpectedToLoad: CMTimeRange) { var percentComplete = 0.0 // 遍历已加载时间范围,累加总加载时长 for value in loadedTimeRanges { let loadedRange = value.timeRangeValue percentComplete += CMTimeGetSeconds(loadedRange.duration) } // 计算总预期时长,避免除以0 let totalDuration = CMTimeGetSeconds(timeRangeExpectedToLoad.duration) if totalDuration > 0 { percentComplete = (percentComplete / totalDuration) * 100 } // 关键:切到主线程更新UI DispatchQueue.main.async { // 这里要确保拿到正确的cell,避免复用坑 if let indexPath = self.findIndexPathForTask(assetDownloadTask), let cell = self.tableView.cellForRow(at: indexPath) as? YourCustomCell { cell.downloadProgressLabel.text = String(format: "%.1f%%", percentComplete) } } }
2. UITableViewCell复用导致引用错误
如果你直接持有了cell的引用,当cell被滚动出屏幕复用给其他行时,你更新的就不是原来那行的cell了。正确的做法是用数据模型驱动UI,而不是直接操作cell。
步骤:
- 先定义一个数据模型来管理下载任务和进度:
struct DownloadItem { let task: AVAssetDownloadTask var progress: Double = 0.0 // 可以再加其他字段,比如音频名称等 } // 用数组管理所有下载项 var downloadItems: [DownloadItem] = []
- 在代理方法里更新对应模型的进度,然后刷新cell:
func urlSession(_ session: URLSession, assetDownloadTask: AVAssetDownloadTask, didLoad timeRange: CMTimeRange, totalTimeRangesLoaded loadedTimeRanges: [NSValue], timeRangeExpectedToLoad: CMTimeRange) { var percentComplete = 0.0 // 进度计算逻辑同上... // 找到当前任务对应的模型 if let index = downloadItems.firstIndex(where: { $0.task == assetDownloadTask }) { downloadItems[index].progress = percentComplete // 主线程刷新对应行的cell DispatchQueue.main.async { let indexPath = IndexPath(row: index, section: 0) // 根据你的实际section调整 self.tableView.reloadRows(at: [indexPath], with: .none) } } }
- 在
tableView(_:cellForRowAt:)方法里,从模型取进度设置label:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell(withIdentifier: "YourCellIdentifier", for: indexPath) as? YourCustomCell else { return UITableViewCell() } let item = downloadItems[indexPath.row] cell.downloadProgressLabel.text = String(format: "%.1f%%", item.progress) return cell }
3. 进度计算逻辑错误
最后检查下你的进度计算是否正确:
- 确保遍历
loadedTimeRanges时,正确累加了每个时间范围的duration - 确保
timeRangeExpectedToLoad.duration是有效的(不为0),否则百分比会一直是0
按照这几步调整,应该就能解决UILabel无法更新的问题了。
内容的提问来源于stack exchange,提问作者Tejasvi Tandon
相关产品推荐
相关产品推荐

