如何完成将图像上传到Firebase存储,然后将imageUrl保存到Firebase数据库

时间:2017-05-18 12:55:01

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

我没有找到满意的答案,希望你有任何想法。我想将我的图片上传到Firebase存储空间并将imageUrls保存到Firebase数据库中。

     var imageUrls = [String]()

     func uploadImagesToStorage(imagesArray: [UIImage]) {


    for i in imagesArray {

        guard let uploadData = UIImageJPEGRepresentation(i, 0.3) else { return }
        let fileName = NSUUID().uuidString

         FIRStorage.storage().reference().child("post_Images").child(fileName).put(uploadData, metadata: nil) { (metadata, err) in

            if let err = err {
            return
            }

            guard let profileImageUrl = metadata?.downloadURL()?.absoluteString else { return }
            self.imageUrls.append(profileImageUrl)

        }.resume()

  } //..End loop
       saveToDatabaseWithImageUrl(imageUrls: imageUrls)

上传图片可以使用 uploadImagesToStorage(imagesArray:[UIImage]) 方法。此方法获取一个数组作为参数,其中包含我要上载的图像。在上传图像时,我从firebase给我的元数据中下载imageUrl信息,并将该imageUrl保存到 imageUrls 数组中。 For循环是保存每个图像的imageUrl信息所必需的。上传图像并使用imageUrl信息填充imageUrls数组时,我调用函数 func saveToDatabaseWithImageUrl(imageUrls:[String]) 将imageUrls保存到数据库中。检查Firebase我发现图像已保存到Firebase存储中,但imageUrls未保存到Firebase数据库中。在调试我的代码时,我发现这种行为的原因是,在上传图像时,代码会跳转到下一行。因此它使用空的imageUrls数组调用saveToDatabaseWithImageUrls。我阅读了[Documentation] [1],并尝试使用.resume()方法管理上传。它仍然跳转到saveToDatabaseWithImageUrl方法。我不知道如何保证上传完成,然后执行下一行代码。谢谢你的帮助。

1 个答案:

答案 0 :(得分:2)

它的发生是因为.child("post_Images").child(fileName).put的成功阻止异步调用。其余代码同步。因此,您for开始上传照片,之后您将URL保存到数据库,但网址为空,因为您不等待完成上传。

我基于DispathGroup

为您提供了完美的解决方案
//Create DispatchGroup
let fetchGroup = DispatchGroup()

for i in imagesArray {
    guard let uploadData = UIImageJPEGRepresentation(i, 0.3) else { return }

    let fileName = NSUUID().uuidString
    //Before every iteration enter to group
    fetchGroup.enter()        
    FIRStorage.storage().reference().child("post_Images").child(fileName).put(uploadData, metadata: nil) { (metadata, err) in
        if let err = err {
        fetchGroup.leave()
        return
        }

        guard let profileImageUrl = metadata?.downloadURL()?.absoluteString else { return }
        self.imageUrls.append(profileImageUrl)
        //after every completion asynchronously task leave the group
        fetchGroup.leave()
    }.resume()
}

了解id magic

fetchGroup.notify(queue: DispatchQueue.main) {
    //this code will call when number of enter of group will be equal to number of leaves from group
    //save your url here
    saveToDatabaseWithImageUrl(imageUrls: imageUrls)
}

此解决方案不会阻塞线程,所有内容都在这里异步工作。