Swift中Firebase Storage下载发票无反应问题求助
问题原因分析
你的代码核心问题有两个:
- 下载完成后未触发文件预览:调用
downloadInvoice后,你没有将返回的文件URL赋值给@State private var fileToPreview,导致QLPreviewControllerRepresentation无法感知到文件已下载,自然不会显示任何内容。 - 缺少错误处理:下载过程中如果抛出异常,没有任何提示,你无法得知是否出现错误。
另外,你将QLPreviewController放在background中的做法并不合适,这种方式不会自动弹出预览界面,需要通过弹窗方式触发。
修复方案
1. 修改按钮点击逻辑,处理返回值与错误
将按钮的Task代码修改为:
Button { Task{ do { if let downloadedURL = try await downloadInvoice(forSolde: solde) { // 将下载好的文件URL赋值给预览变量 fileToPreview = downloadedURL } else { toastMessage = "无法获取文件URL" isShowingToast = true } } catch { toastMessage = "下载失败:\(error.localizedDescription)" isShowingToast = true } } } label: { Text("Voir la facture").multilineTextAlignment(.center) }
2. 调整QLPreviewController的展示方式
将原来的background改为sheet,当fileToPreview不为nil时弹出预览界面:
var body: some View { content.onAppear{ Task{ await adminUserToPaid.fetchSoldeData() soldes = adminUserToPaid.soldeList } } .toast(isShowing: $isShowingToast, text: Text(toastMessage)) // 替换background为sheet .sheet(item: $fileToPreview) { url in QLPreviewControllerRepresentation(fileURL: .constant(url)) } }
同时需要让URL遵循Identifiable协议,在文件末尾添加扩展:
extension URL: Identifiable { public var id: String { absoluteString } }
3. 优化下载函数(可选)
可以在下载前检查文件是否已存在,避免重复下载:
func downloadInvoice(forSolde solde: Solde) async throws -> URL? { let filename = solde.facture let soldeCollection = Firestore.firestore().collection("solde") guard let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { throw NSError(domain: "AppError", code: 1001, userInfo: ["message": "Erreur lors de la récupération du chemin du dossier Documents"]) } let fileURL = documentsURL.appendingPathComponent(filename) // 检查文件是否已存在,存在则直接返回 if FileManager.default.fileExists(atPath: fileURL.path) { return fileURL } let document = try await soldeCollection.document(solde.id).getDocument() guard let documentData = document.data(), let proprietaireUID = documentData["proprietaire"] as? String else { throw NSError(domain: "AppError", code: 1002, userInfo: ["message": "Impossible de trouver le champ proprietaire dans le document"]) } return try await withCheckedThrowingContinuation { continuation in let storageRef = Storage.storage().reference().child("invoices/\(proprietaireUID)/\(solde.id)/\(filename)") storageRef.write(toFile: fileURL) { url, error in if let error = error { continuation.resume(throwing: error) } else if let url = url { continuation.resume(returning: url) } else { continuation.resume(throwing: NSError(domain: "AppError", code: 1003, userInfo: ["message": "Erreur inconnue lors du téléchargement"])) } } } }
验证说明
修改后,点击“Voir la facture”按钮:
- 若下载成功,会自动弹出QLPreviewController展示发票文件
- 若下载失败,会通过toast提示错误信息
- 重复点击时,若文件已存在会直接预览,无需重复下载
内容的提问来源于stack exchange,提问作者Windows Frame
相关产品推荐
相关产品推荐

