我正在制作一张表格,上传3-4张照片到火柴仓库。在上传完所有照片后,我想要执行一个segue
self.performSegue(withIdentifier: "createClubToClubDetail", sender: self)在打电话给performSegue之前,我如何检查是否所有的照片都被上传到了火场。
将上面的代码放在for循环之后不能工作,因为上传照片在不同的线程中运行(?)
let storageRef = Storage.storage().reference(forURL: "xxxxx.appspot.com").child("club_photo").child(clubRef.key)
for p in selectedImage {
let imageData = UIImageJPEGRepresentation(p.value, 0.005)
let storageImgRef = storageRef.child(p.key + ".jpg")
storageImgRef.putData(imageData!, metadata: nil) { (metadata, error) in
if error != nil {
print(error!)
return
}
let downloadURL = metadata?.downloadURL()?.absoluteString
var photoRef: DatabaseReference!
if p.key == "main" {
photoRef = ref.child("photo").child(clubRef.key).child("main")
}
if p.key == "sub1" {
photoRef = ref.child("photo").child(clubRef.key).child("sub1")
}
if p.key == "sub2" {
photoRef = ref.child("photo").child(clubRef.key).child("sub2")
}
if p.key == "sub3" {
photoRef = ref.child("photo").child(clubRef.key).child("sub3")
}
photoRef.setValue(downloadURL)
print("Upload photo: \(p.key)")
}
}
self.performSegue(withIdentifier: "createClubToClubDetail", sender: self)发布于 2017-09-07 00:24:05
如前所述,标准的DispatchGroup API能够为您的问题提供一个很好的解决方案。由于您可能在应用程序的其他地方也需要此功能,所以我尝试将基于DispatchGroup的解决方案封装在一个很好的助手类中:
//
// UploadTracker.swift
//
import Foundation
import FirebaseDatabase
class UploadTracker {
private let group = DispatchGroup()
fileprivate func trackSetValue(_ value: Any?, ref: DatabaseReference) {
group.enter()
ref.setValue(value) { (error, _) in
assert(error != nil, "\(error)")
self.group.leave()
}
}
func uploadDidFinish(block: @escaping () -> Void) {
group.notify(queue: .main) { block() }
}
}
extension DatabaseReference {
func setValue(_ value: Any?, trackedBy tracker: UploadTracker) {
tracker.trackSetValue(value, ref: self)
}
}在您的原始代码中,其用法是:
let uploadTracker = UploadTracker()
for p in selectedImage {
...
photoRef.setValue(downloadURL, trackedBy: uploadTracker)
}
uploadTracker.uploadDidFinish {
self.performSegue(withIdentifier: "createClubToClubDetail", sender: self)
}发布于 2017-10-24 12:41:23
我已经尝试了下面的代码上传多个图像,并在上次上传完成后执行segue,虽然这是一个临时修复,但它有效。
当用户希望将多个映像保存到firebase存储时,将调用saveToServerButtonPressed方法。selectedImages是UiImage类型的数组,具有用户希望上载的所有图像。保留var counter仅仅是为了捕获最后一个图像的成功上传,这样用户就可以导航到其他屏幕/任何其他任务,而这些任务只有在所有上传完成之后才能完成。
@IBAction func saveToServerButtonPressed(_ sender: Any) {
var counter = 0
for image in selectedImages {
uploadImage(image, progressBlock: { (progressValue) in
self.progressStatus.text = "\(progressValue)%"
}) { (downloadUrl, error) in
if error == nil {
if let downloadUrl1 = downloadUrl
{
counter += 1
self.imagesUrls.append(downloadUrl1)
if counter == self.selectedImages.count {
self.performSegue(withIdentifier: "showDownloadedSegue", sender: self)
}
}
} else {
print("Error Occured \(String(describing: error))")
}
}
}
}方法,该方法将图像实际上载到firebase上。
func uploadImage(_ image: UIImage, progressBlock: @escaping (_ percentage: Double) -> Void, completionBlock: @escaping (_ url: URL?, _ errorMessage: String?) -> Void) {
let storage = FIRStorage.storage()
let storageReference = storage.reference()
let imageName = "\(Date().timeIntervalSince1970).jpg"
let imagesReference = storageReference.child(imageName)
if let imageData = UIImageJPEGRepresentation(image, 0.8) {
let metadata = FIRStorageMetadata()
metadata.contentType = "image/jpeg"
let uploadTask = imagesReference.put(imageData, metadata: metadata, completion: { (metadata, error) in
if let metadata = metadata {
completionBlock(metadata.downloadURL(), nil)
} else {
completionBlock(nil, error?.localizedDescription)
}
})
uploadTask.observe(.progress, handler: { (snapshot) in
guard let progress = snapshot.progress else {
return
}
let percentage = (Double(progress.completedUnitCount) / Double(progress.totalUnitCount)) * 100
progressBlock(percentage)
})
} else {
completionBlock(nil, "Image couldn't be converted to Data.")
}
}
}注意:这段代码在Swift 4上运行良好
https://stackoverflow.com/questions/46077763
复制相似问题