SwiftUI二手交易App中Firebase图片链接存入Firestore失败问题
SwiftUI Firebase 图片上传后链接无法存入Firestore问题解决
我在开发SwiftUI二手交易App时,尝试将图片上传至Firebase Storage并获取链接存入Firestore,但操作失败——图片链接未能正确关联到对应的商品数据中。
核心代码
上传图片函数uploadPhoto
func uploadPhoto() { // Make sure that the selected image poperty isn't nil guard selectedImage != nil else{ return } let storageRef = Storage.storage().reference() //Turn our image into data let imageData = selectedImage!.jpegData(compressionQuality: 0.8) guard imageData != nil else { return } // Specify the file path an name let path = "images/\(UUID().uuidString).jpg" let fileRef = storageRef.child(path) // Upload that data let uploadTask = fileRef.putData(imageData!) { metadata, error in if error == nil && metadata != nil { fileRef.downloadURL { url, error in guard let url = url, error == nil else { return } let urlString = url.absoluteString print("Download url: \(urlString)") self.imageUrl = urlString let firestoreRef = Firestore.firestore() firestoreRef.collection("users").document().setData(["items": urlString]) } } } }
添加数据函数addData
// Add data func addData(items: Items) { if let currentUser = currentUser { do { try db.collection("users").document(currentUser.uid).updateData(["items": FieldValue.arrayUnion([Firestore.Encoder().encode(items)])]) } catch { print("Error occured retriving data") } } }
数据模型
struct UserData: Codable, Identifiable { @DocumentID var id: String? var items: [Items] } struct Items: Codable, Identifiable { var id = UUID() var title: String var price: String var description: String var image: String? }
触发逻辑
VStack (spacing: 25){ Button { if selectedImage != nil { uploadPhoto() } if title != "" && price != "" && description != "" { viewModel.addData(items: Items(title: title, price: price, description: description, image: imageUrl)) } } label: { Text("Publish").font(.buttonTitle) }.buttonStyle(CustomButton()) }
问题原因
- 异步操作顺序错误:
uploadPhoto是异步操作,获取下载URL并赋值imageUrl的逻辑在回调中执行,但按钮点击时addData会立刻触发,此时imageUrl大概率还未被赋值,导致存入Firestore的image字段为空。 - Firestore写入逻辑冲突:
uploadPhoto中直接创建了新的users文档(firestoreRef.collection("users").document().setData(...)),生成了无关联的无效文档,和addData更新当前用户文档的逻辑矛盾。
解决方案
1. 给uploadPhoto添加完成回调,确保异步流程顺序
修改上传函数,通过闭包返回图片链接,让外部在上传完成后再执行后续操作:
func uploadPhoto(completion: @escaping (String?) -> Void) { guard let selectedImage = selectedImage else { completion(nil) return } guard let imageData = selectedImage.jpegData(compressionQuality: 0.8) else { completion(nil) return } let storageRef = Storage.storage().reference() let path = "images/\(UUID().uuidString).jpg" let fileRef = storageRef.child(path) fileRef.putData(imageData) { metadata, error in guard error == nil, metadata != nil else { completion(nil) return } fileRef.downloadURL { url, error in guard let url = url, error == nil else { completion(nil) return } completion(url.absoluteString) } } }
2. 调整按钮触发逻辑,等待上传完成再添加商品
VStack (spacing: 25){ Button { guard title != "", price != "", description != "" else { print("请填写完整商品信息") return } if let _ = selectedImage { viewModel.uploadPhoto { imageUrl in guard let imageUrl = imageUrl else { print("图片上传失败") return } viewModel.addData(items: Items(title: title, price: price, description: description, image: imageUrl)) } } else { viewModel.addData(items: Items(title: title, price: price, description: description, image: nil)) } } label: { Text("Publish").font(.buttonTitle) }.buttonStyle(CustomButton()) }
3. 移除uploadPhoto中无效的Firestore写入代码
删除以下代码,避免生成无关联的用户文档:
let firestoreRef = Firestore.firestore() firestoreRef.collection("users").document().setData(["items": urlString])
4. 优化addData的错误处理
让错误信息更明确:
func addData(items: Items) { guard let currentUser = currentUser else { print("未获取到当前用户") return } do { let encodedItem = try Firestore.Encoder().encode(items) try db.collection("users").document(currentUser.uid).updateData(["items": FieldValue.arrayUnion([encodedItem])]) print("商品数据添加成功") } catch { print("添加数据失败: \(error.localizedDescription)") } }
内容的提问来源于stack exchange,提问作者Rohullah
相关产品推荐
相关产品推荐

