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.