SwiftUI新Alert API无法更新下载进度文本,求解决方案
解决SwiftUI新Alert API无法动态更新下载进度的问题
问题原因
新的.alert(isPresented:actions:message:) API中,message闭包仅在Alert首次呈现时执行一次,后续ViewModel的进度状态变化不会自动触发Alert内容更新。而旧的废弃API会在每次视图重绘时重新生成Alert实例,因此能动态获取最新进度。
解决方案1:确保状态正确发布与追踪
首先保证ViewModel中的进度相关属性通过@Published发布,让SwiftUI能感知变化:
class DownloadViewModel: ObservableObject { @Published var downloadProgress: Double = 0.0 // 基于发布的进度计算格式化文本 var formattedProgressInPercent: String { String(format: "%.0f%%", downloadProgress * 100) } func onCancelDownloadTaped() { // 取消下载逻辑 } }
随后修改Alert调用,利用SwiftUI的状态追踪机制触发内容更新:
.alert("Prepare download", isPresented: $showingAlert, actions: { Button("Cancel", role: .cancel) { viewModel.onCancelDownloadTaped() } }, message: { Text("The video will be downloaded ... (\(viewModel.formattedProgressInPercent))") } )
由于formattedProgressInPercent依赖@Published的downloadProgress,进度变化时会自动触发Text更新。
解决方案2:使用.alert(item:) API(更可靠)
如果上述方法仍无效果,推荐使用基于Identifiable的.alert(item:) API,它会在绑定的item变化时重新构建Alert,确保内容动态更新:
- 定义符合
Identifiable的Alert数据模型:
struct DownloadAlertItem: Identifiable { let id = UUID() var progressText: String let cancelAction: () -> Void }
- 在ViewModel中添加对应的发布属性与更新方法:
class DownloadViewModel: ObservableObject { @Published var downloadProgress: Double = 0.0 @Published var downloadAlertItem: DownloadAlertItem? func updateAlert() { let progressText = String(format: "%.0f%%", downloadProgress * 100) downloadAlertItem = DownloadAlertItem( progressText: progressText, cancelAction: { [weak self] in self?.onCancelDownloadTaped() } ) } func onCancelDownloadTaped() { // 取消下载逻辑 downloadAlertItem = nil } }
- 在视图中使用该API:
.alert(item: $viewModel.downloadAlertItem) { item in Alert( title: Text("Prepare download"), message: Text("The video will be downloaded ... (\(item.progressText))"), dismissButton: .cancel(Text("Cancel"), action: item.cancelAction) ) }
每次下载进度更新时,调用viewModel.updateAlert()即可刷新Alert中的进度文本。
内容的提问来源于stack exchange,提问作者Strassenrenner
相关产品推荐
相关产品推荐

