2

I'm trying to create a function that uploads images to Firebase Storage and returns the download url for their path so I can use it other parts of the app.

This is what the function looks like:

func uploadImage(to reference:StorageReference, image:UIImage) -> URL? {

        let imageData = UIImageJPEGRepresentation(image, 0.2)
        let metadata = StorageMetadata()
        metadata.contentType = "image/jpeg"
        var downloadURL = metadata.downloadURL()
        reference.putData(imageData!, metadata: metadata) { (metadata, error) in
            if error != nil {
                print("Couldnt upload due to \(String(describing: error))")
            }
            downloadURL = metadata?.downloadURL()
        }
        return downloadURL!
    }

I can't seem to get the result that I want as downloadUrl always returns nil. What am I doing wrong?

AAAM
  • 31
  • 3

1 Answers1

1

The problem here is that your function is returning before the upload is complete. In other words your function needs to return a callback, rather than a plain URL. Something like -

func uploadImage(to reference:StorageReference, image:UIImage, completion: @escaping (URL?) -> Void) {
    let imageData = UIImageJPEGRepresentation(image, 0.2)
    let metadata = StorageMetadata()
    metadata.contentType = "image/jpeg"
    var downloadURL = metadata.downloadURL()
    reference.putData(imageData!, metadata: metadata) { (metadata, error) in
        if error != nil {
            print("Couldnt upload due to \(String(describing: error))")
            completion(nil)
        } else {
             if let downloadUrl = metadata?.downloadURL() {
                completion(downloadUrl)
            } else {
                completion(nil)
            }
        }
    }
}
Chris Edgington
  • 2,937
  • 5
  • 23
  • 42
  • Hi Chris, Thank you for replying. So is there any other way that I can use a function that takes a UIImage as its parameter, uploads it to Storage and finally returns a URL after the upload has been completed? – AAAM Dec 12 '17 at 15:05
  • The above example will give you a URL, you just need to make sure you use a callback. Take a look at the Swift documentation on Closures if you're unfamiliar - https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html – Chris Edgington Dec 12 '17 at 15:51
  • Also look at https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call/14220323#14220323 for a more general explanation. – Chris Edgington Dec 12 '17 at 15:58