2
votes

I am trying to allow users to upload a profile photo to Firebase Storage. The image gets uploaded during the sign up process of my app. The image is being uploaded to Firebase Storage properly, however, the download URL is not uploading to Google Cloud Firestore.

I've already tried to change my variable downloadURL of type String to hold an empty String. This did not change the result.

Here is the code to upload the profile photo to Firebase Storage:

func uploadProfilePic() -> String {
     guard let imageData = profilePic?.jpegData(compressionQuality: 0.75) else {
         print("Unable to get image data.")
         return ""
     }

     let imageID = UUID().uuidString
     let profilePhotosRef = Storage.storage().reference().child("profilePhotos/\(imageID).jpg")

     let uploadMetadata = StorageMetadata()
     uploadMetadata.contentType = "image/jpeg"

     var downloadURL = String()
     profilePhotosRef.putData(imageData, metadata: uploadMetadata) { (downloadMetadata, err) in
         if let err = err {
             self.showAlertWithOK(title: "An Error Occurred", message: "There was an error uploading your profile photo. Try again later in Hostend settings.")
             print("An error occurred: \(err.localizedDescription)")
         }

         profilePhotosRef.downloadURL { (url, err) in
             if let url = url {
                 downloadURL = url.absoluteString
             }
         }
     }

     return downloadURL
}

Here is the code for uploading the profile photo download URL to Cloud Firestore:

db.collection("users").document(uid).setData(["profile_pic_url": uploadProfilePic(), "name": name, "phone_number": phoneNumber, "fcm_token": token, "timestamp": Date()])

The uploadProfilePic() method returns a String.

I expected the download URL of the image to be uploaded to Firestore under "profile_pic_url," but that did not happen. Instead, it is just an empty String even though the image had been successfully to Firebase Storage.

1
Did you console.log() ed the return of your method uploadProfilePic()?Constantin Beer

1 Answers

2
votes

You can't use a return statement for a function that contains a closure as the function will return before the closure has executed.

Instead change your function to use a completion handler such as

func uploadProfilePic(completion: @escaping (String?, Error?) -> ()) {

Then once you get your download url call the handler.

    profilePhotosRef.downloadURL { (url, err) in
      completion(url, err)
    }

You can then use this function to populate your call to Cloud Firestore like so

   self.uploadProfilePic() { (url, error) in

    guard error....

    if let url = url {
      // do your upload here
    }
}