SwiftUI List点击下载时ProgressView全行显示问题求助
问题原因
你当前使用了一个全局的progress变量,所有列表行的ProgressView都绑定到这个变量上。当任意一个下载任务更新进度时,这个全局变量的值会改变,导致所有行的进度条同步显示相同的进度。
解决方案
需要为每一个书籍条目维护独立的下载进度,而不是使用全局变量。这里提供两种可行的实现方式:
方式一:修改Book模型添加进度属性
如果可以修改Book结构体的定义,直接给它添加一个下载进度属性:
struct Book { let bookId: Int // 假设原有属性 let name: String // 假设原有属性 // 添加进度属性,默认值0.0 var downloadProgress: Double = 0.0 }
然后调整列表代码,绑定对应书籍的进度:
List { ForEach($books) { $book in // 使用绑定方式访问单个Book VStack { Text(book.name) .font(.system(size: 22)) .listRowSeparator(.hidden) Button(NSLocalizedString("Download", comment: "")) { let downloadAudio = DownloadAudio() downloadAudio.downloadBookId(Int32(book.bookId), testamentId: Int32(self.testamentId), forLanguage: self.item.language) { _, progress, error in // 更新当前书籍的进度 book.downloadProgress = progress print(progress) } } .buttonStyle(.borderedProminent) .controlSize(.large) // 绑定到当前书籍的进度属性 ProgressView(value: book.downloadProgress, total: 1.0) } } .listRowSeparator(.hidden) }
方式二:使用字典存储独立进度(不修改原模型)
如果无法修改Book的原始定义,可以用一个字典来存储每个书籍ID对应的下载进度:
// 在视图中添加这个状态变量 @State private var downloadProgresses: [Int: Double] = [:] // 列表代码调整: List { ForEach(0..<self.books.count, id: \.self) { index in let thisBook = self.books[index] // 获取当前书籍的进度,默认0.0 let currentProgress = self.downloadProgresses[thisBook.bookId] ?? 0.0 VStack { Text(thisBook.name) .font(.system(size: 22)) .listRowSeparator(.hidden) Button(NSLocalizedString("Download", comment: "")) { let downloadAudio = DownloadAudio() downloadAudio.downloadBookId(Int32(thisBook.bookId), testamentId: Int32(self.testamentId), forLanguage: self.item.language) { _, progress, error in // 更新字典中对应书籍ID的进度 self.downloadProgresses[thisBook.bookId] = progress print(progress) } } .buttonStyle(.borderedProminent) .controlSize(.large) // 绑定到当前书籍的进度值 ProgressView(value: currentProgress, total: 1.0) } } .listRowSeparator(.hidden) }
额外说明
- 两种方式的核心都是让每个列表行的
ProgressView绑定到对应书籍的独立进度值,而非全局变量。 - 如果下载任务可能被取消或重置,可以在需要时将对应书籍的进度重置为0.0。
内容的提问来源于stack exchange,提问作者neowinston
相关产品推荐
相关产品推荐

