Reputation:
When my user signs up, they are using a profile image that goes directly to firebase. The image uploads into firebase storage the properly but once it appears in the database the profile image URL is missing also in the debug area the image link is showing up as optional. What should I change in this code to properly upload the image link into the firebase database?
if let AuthData = AuthDataResult {
print(AuthData.user.email)
var dict : Dictionary < String, Any> = [
"uid": AuthData.user.uid,
"username": self.UsernameTextField.text!,
"email": AuthData.user.email,
"ProfileImageUrl": "",
]
let storage = Storage.storage()
let storageRef = storage.reference()
let imageName = UUID().uuidString
let imageReference = Storage.storage().reference().child(imageName)
//2. Compress quality
if let uploadData = self.ProfileImage.image?.jpegData(compressionQuality: 0.5){
//3. Save image as .jpeg
let metaDataForImage = StorageMetadata()
metaDataForImage.contentType = "image/jpeg"
//4. Add the data to Firebase Storage
imageReference.putData(uploadData, metadata: metaDataForImage) { (meta, err) in
if let err = err{
print(err.localizedDescription)
} else {
//5. Retrieving the image URL
imageReference.downloadURL { (url, err) in
if let err = err{
print(err.localizedDescription)
} else {
//6. Print the complete URL as string
let urlString = url?.absoluteString
print(urlString)
}
Database.database().reference().child("users").child(AuthData.user.uid).updateChildValues(dict, withCompletionBlock: { (error,ref) in
if error == nil {
print("Done")
return
}
Upvotes: 0
Views: 756
Reputation: 35657
It appears that all of the code in the question is within the AuthData var.
The issue is caused by one of the key: value pairs within the dict var being an empty string. I'll shorten this up a bit to highlight the issue. Here's the original code with my added comments:
if let AuthData = AuthDataResult {
var dict : Dictionary < String, Any> = [
"uid": AuthData.user.uid,
"username": self.UsernameTextField.text!,
"email": AuthData.user.email,
"ProfileImageUrl": "", // <--- Profile ImageUrl is an empty string
]
imageReference.putData(uploadData, metadata: metaDataForImage) { (meta, err) in
if let err = err{
} else {
imageReference.downloadURL { (url, err) in
if let err = err{
} else {
let urlString = url?.absoluteString
}
//The ProfileImageUrl key: value pair within the **dict** var is an
// empty string at this point, so no url is written.
let dbRef = Database.database().reference()
let usersRef = dbRef.child("users").child(AuthData.user.uid)
usersRef.updateChildValues(dict, withCompletionBlock: { (error,ref) in
if error == nil {
print("Done")
return
}
//note that if an error occurs, the code silently fails
To fix, populate the dict with the data you want written.
Here's a corrected section of the code which includes error checking and populating the ProfileImageUrl with the download url and then writing it to Firebase.
imageReference.downloadURL { (url, error) in
if let err = error {
print(err.localizedDescription)
return
}
guard let validUrl = url else {
print("url was not valid")
return
}
let urlString = validUrl.absoluteString
dict["ProfileImageUrl"] = urlString //update the dict with the url
let dbRef = Database.database().reference()
let usersRef = dbRef.child("users").child(AuthData.user.uid)
usersRef.updateChildValues(dict, withCompletionBlock: { error, ref in
if let err = error {
print(err.localizedDescription)
return
}
print("Successfully wrote auth data and url")
})
}
Upvotes: 1
Reputation: 598857
My educated guess is that you're writing the user information to the database when the upload hasn't completed, or the download URL hasn't yet been retrieved. Both uploading and requesting the download URL are asynchronous operations, meaning that any code that depends on them being completed needs to be inside the closure that gets executed when the operation completes (or be called from there).
let storage = Storage.storage()
let storageRef = storage.reference()
let imageName = UUID().uuidString
let imageReference = Storage.storage().reference().child(imageName)
//2. Compress quality
if let uploadData = self.ProfileImage.image?.jpegData(compressionQuality: 0.5){
//3. Save image as .jpeg
let metaDataForImage = StorageMetadata()
metaDataForImage.contentType = "image/jpeg"
//4. Add the data to Firebase Storage
imageReference.putData(uploadData, metadata: metaDataForImage) { (meta, err) in
if let err = err{
print(err.localizedDescription)
}
else{
//5. Retrieving the image URL
imageReference.downloadURL { (url, err) in
if let err = err{
print(err.localizedDescription)
}
else{
//6. Print the complete URL as string
let urlString = url?.absoluteString
print(urlString)
// 7. Write the URL to the database here <--
}
Upvotes: 0