SwiftUI中使用Alamofire上传音频至REST API时如何显示加载动画直至获取响应?
SwiftUI 实现上传音频时的转圈加载效果
核心实现逻辑
SwiftUI 采用状态驱动UI的模式,无需手动操作视图的显隐,只需要通过一个布尔状态值控制加载组件的展示时机,在上传流程的生命周期节点修改这个状态即可。
具体实现步骤
- 在视图中新增
@State修饰的布尔变量,标记当前是否处于上传流程中 - 触发上传前,将该状态值设为
true,自动触发加载视图的展示 - 在接口响应回调中,无论请求成功、失败,都在主线程将该状态值设为
false,关闭加载视图 - 在页面的视图层级中,通过条件判断叠加系统自带的加载指示器(默认就是带动画的转圈样式)
完整适配原有逻辑的代码示例
保留你原来写的Alamofire上传逻辑,只补充状态控制和UI叠加部分:
import SwiftUI import Alamofire import AVFoundation struct AudioUploadView: View { // 控制加载显隐的状态变量 @State private var isUploading = false // 按需存储接口返回的提示信息 @State private var uploadTip = "" // 保留你原有的录音器实例 let audioRecorder: AVAudioRecorder var body: some View { ZStack { // 原有页面内容 VStack(spacing: 16) { Button("开始上传录音") { startAudioUpload() } if !uploadTip.isEmpty { Text(uploadTip) } } // 加载提示层:仅上传中显示 if isUploading { ProgressView("正在上传,请稍候") .progressViewStyle(CircularProgressViewStyle()) .padding(20) .background(.ultraThinMaterial) .cornerRadius(10) } } } // 抽取的独立上传方法 private func startAudioUpload() { // 先做文件存在性校验,避免强制解包导致崩溃 guard let voiceData = try? Data(contentsOf: audioRecorder.url) else { uploadTip = "音频文件读取失败" return } let uploadUrl = "<server ip>" // 进入上传状态,触发加载视图展示 isUploading = true AF.upload(multipartFormData: { multipartFormData in multipartFormData.append(voiceData, withName: "file", fileName: "recording.m4a", mimeType: "audio/mpeg") }, to: uploadUrl, method: .post) .responseJSON { resp in // UI更新必须在主线程执行 DispatchQueue.main.async { // 无论请求结果如何,先关闭加载提示 isUploading = false // 后续按你的需求处理响应 print(resp) } } } }
常见注意事项
- Alamofire的响应回调默认在子线程执行,所有和UI相关的状态更新必须切换到主线程,否则会出现加载圈不消失、UI偶发卡顿的问题
- 建议把Alamofire返回的
UploadRequest实例存为视图的属性,在用户离开页面、取消上传操作时主动调用cancel()方法终止请求,同时重置isUploading状态,避免内存泄漏 - 系统自带的
ProgressView已经内置了旋转动画,不需要手动编写动画代码,适配绝大多数场景的加载提示需求,也可以根据需要自定义指示器的样式
内容的提问来源于stack exchange,提问作者Erik
相关产品推荐
相关产品推荐

