I want to know how to use async/await in for by Swift.
var data = [String]()
func uploadImage(images: [UIImage]) async -> Array<String> {
for image in images{
ImageUploader.uploadImages(image: image, type: .post) { imageUrl async in
await self.data.append(imageUrl)
}
}
return data
}
static func uploadImages(image: UIImage,type: UploadType,completion: @escaping(String) -> Void) async{
guard let imageData = image.jpegData(compressionQuality: 0.5) else{return}
let ref = type.filePath
ref.putData(imageData,metadata: nil){ _, error in
if let error = error{
print("DEBUG: Failed to upload image\(error.localizedDescription)")
return
}
print("Successfully uploaded image")
ref.downloadURL{ url, _ in
guard let imageUrl = url?.absoluteString else {return}
completion(imageUrl)
}
}
}
When I call the func uploadImage, not waiting for self.data.append(imageUrl)
The data return empty array.
I want for uploadImage
to wait append
,then the string array should return array including uploadImages'imageUrl.
How should I correct this. Thank you.
It looks like since the last time I looked at the API Firebase has provided its own async/await
methods. For uploading images it is imageRef.putDataAsync(imageData)
.
///Uploads Data to the designated path in `FirebaseStorage`
static func upload(imageData: Data, path: String) async throws -> URL{
let storageRef = storage.reference()
let imageRef = storageRef.child(path)
let metadata = try await imageRef.putDataAsync(imageData)
return try await imageRef.downloadURL()
}
Then you can use withThrowingTaskGroup
to upload simultaneously or use a regular for
loop to upload 1x1.
import UIKit
import FirebaseStorageSwift
import FirebaseStorage
struct ImageStorageService{
static private let storage = Storage.storage()
///Uploads a multiple images as JPEGs and returns the URLs for the images
///Runs the uploads simultaneously
static func uploadAsJPEG(images: [UIImage], path: String, compressionQuality: CGFloat = 1) async throws -> [URL]{
return try await withThrowingTaskGroup(of: URL.self, body: { group in
for image in images {
group.addTask {
return try await uploadAsJPEG(image: image, path: path, compressionQuality: compressionQuality)
}
}
var urls: [URL] = []
for try await url in group{
urls.append(url)
}
return urls
})
}
///Uploads a multiple images as JPEGs and returns the URLs for the images
///Runs the uploads one by one
static func uploadAsJPEG1x1(images: [UIImage], path: String, compressionQuality: CGFloat = 1) async throws -> [URL]{
var urls: [URL] = []
for image in images {
let url = try await uploadAsJPEG(image: image, path: path, compressionQuality: compressionQuality)
urls.append(url)
}
return urls
}
///Uploads a single image as a JPG and returns the URL for the image
///Runs the uploads simultaneously
static func uploadAsJPEG(image: UIImage, path: String, compressionQuality: CGFloat = 1) async throws -> URL{
guard let data = image.jpegData(compressionQuality: compressionQuality) else{
throw ServiceError.unableToGetData
}
return try await upload(imageData: data, path: path)
}
///Uploads Data to the designated path in `FirebaseStorage`
static func upload(imageData: Data, path: String) async throws -> URL{
let storageRef = storage.reference()
let imageRef = storageRef.child(path)
let metadata = try await imageRef.putDataAsync(imageData)
return try await imageRef.downloadURL()
}
enum ServiceError: LocalizedError{
case unableToGetData
}
}