How To Retrieve The Current User Image And Display In ImageView?
I want to learn how to properly retrieve the image from Firebase for the current user.I am trying to get the user ImageUrl
from the User
table and use that url to display the image down below but it does not do it and crashes the app. I want to know if I am doing it properly or doing it wrong.
Thank you in advance
func retrieveTheImage() {
let userID = Auth.auth().currentUser?.uid
let retrieveTheUrl = Database.database().reference().child("User").child(userID!)
var capatureUrl :String = ""
retrieveTheUrl.observeSingleEvent(of: .value) { (snapShot) in
if let snapShotValue = snapShot.value as? Dictionary<String,String>{
let url = snapShotValue["ImageUrl"]! /
capatureUrl = url
print(capatureUrl)
}
}
let storage = Storage.storage()
var reference: StorageReference!
reference = storage.reference(forURL: capatureUrl)
reference.downloadURL { (url, error) in
let data = NSData(contentsOf: url!)
let image = UIImage(data: data! as Data )
self.imageUser.image = image
}
}
Answer
Your code actually works...almost.
The problem with the code is that Firebase is asynchronous so data only becomes valid within the closure following a firebase call.
So here's what's happening (condensed code)
func retrieveTheImage2() {
let userID = Auth.auth().currentUser?.uid
let retrieveTheUrl = Database.database().reference().child("User").child(userID!)
//code in closure//
}
//code after closure//
--> reference = storage.reference(forURL: capatureUrl) //not valid
reference.downloadURL { (url, error) in
}
}
The code after the closure will execute before the //code in closure//.
That means capatureUrl will be nil because it has not been populated yet. Code is faster than the internet.
To fix that, just move the code that accesses data from Firebase within the closure.
func retrieveTheImage2() {
let userID = Auth.auth().currentUser?.uid
let retrieveTheUrl = Database.database().reference().child("User").child(userID!)
var capatureUrl :String = ""
retrieveTheUrl.observeSingleEvent(of: .value) { (snapShot) in
if let snapShotValue = snapShot.value as? Dictionary<String,String>{
let url = snapShotValue["ImageUrl"]!
capatureUrl = url
print(capatureUrl)
let storage = Storage.storage()
var reference: StorageReference!
reference = storage.reference(forURL: capatureUrl) //will be valid here.
reference.downloadURL { (url, error) in
let data = NSData(contentsOf: url!)
let image = UIImage(data: data! as Data )
self.imageUser.image = image
}
}
}
}
In general, it takes time for data to return from the internet and that's the purpose of Firebase closures - that code executes when the data is valid. So if you want to work with Firebase data, only attempt to access it initially within those closures.
Related Questions
- → Function Undefined in Axios promise
- → What are the pluses/minuses of different ways to configure GPIOs on the Beaglebone Black?
- → Click to navigate on mobile devices
- → Playing Video - Server is not correctly configured - 12939
- → How to allow api access to android or ios app only(laravel)?
- → Axios array map callback
- → Access the Camera and CameraRoll on Android using React Native?
- → Update React [Native] View on Day Change
- → Shopify iOS SDK - issue converting BuyProductVariant to BuyProduct
- → BigCommerce and shopify API
- → Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `ListView`
- → React Native - Differences between Android and IOS
- → What is the difference between React Native and React?