如何在调用performSegue之前检查是否所有照片都上传到firebase

时间:2017-09-06 14:24:10

标签: ios swift firebase firebase-realtime-database firebase-storage

我正在制作一张表格,将3-4张照片上传到firebase存储空间。 上传完所有照片后,我想执行一个segue

self.performSegue(withIdentifier: "createClubToClubDetail", sender: self)

如何在调用performSegue之前检查是否所有照片都上传到firebase。

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)

2 个答案:

答案 0 :(得分:2)

如前所述,标准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)
}

答案 1 :(得分:0)

我已尝试使用以下代码上传多张图片并在上次上传完成时执行segue,虽然这是一个临时修复,但它确实有效。

当用户想要将多个图像保存到firebase存储时,会调用

saveToServerButtonPressed方法。 selectedImagesUiImage类型的数组,包含用户要上传的所有图像。 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上运行良好