The problem you're facing happens because the image uploads to Firebase Storage and the download URL fetching happen asynchronously. This means the photoUrls array doesn’t get updated quickly enough before the addCar function runs, so an empty array ends up being sent to Firestore.
@MainActor
class AddCarViewModel: ObservableObject {
@Published var photoUrls: [String] = []
func uploadImages(images: [Image], customerId: String) async throws {
let subFolderId = UUID().uuidString
let pictureFolderRef = Storage.storage().reference().child("CarPhotos").child(customerId).child("\(subFolderId)")
let dispatchGroup = DispatchGroup()
var urls: [String] = []
for (index, image) in images.enumerated() {
guard let imageData = image.asUIImage().jpegData(compressionQuality: 0.5) else {
continue
}
let pictureReference = pictureFolderRef.child("image_\(index).jpeg")
dispatchGroup.enter()
pictureReference.putData(imageData, metadata: nil) { metadata, error in
if let error = error {
print("Failed to upload image: \(error)")
dispatchGroup.leave()
return
}
pictureReference.downloadURL { url, error in
if let error = error {
print("Failed to get download URL: \(error)")
} else if let urlString = url?.absoluteString {
urls.append(urlString)
}
dispatchGroup.leave()
}
}
}
// Wait for all uploads to finish
dispatchGroup.wait()
// Update the photoUrls array
await MainActor.run {
self.photoUrls = urls
}
}
func addCar(carInfo: Car) async throws {
try await Firestore.firestore().collection("cars").document().setData(from: carInfo)
}
}
---
Button {
Task {
do {
try await viewModel.uploadImages(images: selectedImages, customerId: viewModel.user!.uid)
try await viewModel.addCar(carInfo: Car(photoUrls: viewModel.photoUrls))
dismiss()
} catch {
print(error)
}
}
} label: {
Text("Post")
}