Home > database >  Completion not working with Firebase Database
Completion not working with Firebase Database

Time:10-17

The user can upload a profile picture and some information about himself in my app. I want to write the url of the uploaded picture in firebase realtime database but it takes the placeholder text "testentry" and not the real url. Why does my completion not work here?

var imagePicker: UIImagePickerController!
var urltoPicture = "testentry"

@IBAction func updateProfile(_ sender: UIButton) {
       
        uploadPic(arg: true, completion: { (success) -> Void in
               if success {
                   linkUbertragen()
               } else {
                   
               }
           })
        
        
        func uploadPic(arg: Bool, completion: @escaping (Bool) -> ()) {
            
            guard let imageSelected = self.image else {
                //print("ok")
                return
            }
            guard let imageData = imageSelected.jpegData(compressionQuality: 0.1) else {
                return
            }
            let storageRef = Storage.storage().reference(forURL: "gs://h......com")
            let storageProfileRef = storageRef.child("profilePictures").child(Auth.auth().currentUser!.uid)
            let metadata = StorageMetadata()
            metadata.contentType = "image/jpg"
            storageProfileRef.putData(imageData, metadata: metadata, completion: {
                (storageMetadata, error) in
                if error != nil {
                    //print(error?.localizedDescription)
                    return
                }
                storageProfileRef.downloadURL(completion: { (url, error) in
                    if let metaImageURL = url?.absoluteString {
                        print(metaImageURL)
                        self.urltoPicture = metaImageURL
                    }
                })
            })
            
            completion(arg)
        }
        
        func linkUbertragen(){
            ref = Database.database().reference()
            let userID = Auth.auth().currentUser!.uid
            ref.child("user/\(userID)").updateChildValues(["profileText": profileText.text!])
            print(urltoPicture)
            ref.child("user/\(userID)").updateChildValues(["picture": urltoPicture])
        }
                                                       
        self.navigationController?.popViewController(animated: true)
    }

CodePudding user response:

This is a very common mistake. You have to call completion inside the (final) closure.

And it is good practice to call completion(false) always in case of an error – even better to return and handle all errors

func uploadPic(arg: Bool, completion: @escaping (Bool) -> ()) {
        
        guard let imageSelected = self.image else {
            //print("ok")
            completion(false); return
        }
        guard let imageData = imageSelected.jpegData(compressionQuality: 0.1) else {
            completion(false); return
        }
        let storageRef = Storage.storage().reference(forURL: "gs://h......com")
        let storageProfileRef = storageRef.child("profilePictures").child(Auth.auth().currentUser!.uid)
        let metadata = StorageMetadata()
        metadata.contentType = "image/jpg"
        storageProfileRef.putData(imageData, metadata: metadata, completion: {
            (storageMetadata, error) in
            if error != nil {
                //print(error?.localizedDescription)
                completion(false); return
            }
            storageProfileRef.downloadURL(completion: { (url, error) in
                if let metaImageURL = url?.absoluteString {
                    print(metaImageURL)
                    self.urltoPicture = metaImageURL
                    completion(true)
                } else {
                    completion(false)
                }
            })
        })
    }

The arg parameter is actually not needed.

  • Related