I have setup images on my app to work with firebase UI so that I can cache them easily, by following the docs https://firebase.google.com/docs/storage/ios/download-files
My code looks something like this
guard let profileImageUrl = user?.url else { return }
profileImageView.sd_setImage(with: profileImageUrl)
I am overwriting the image location to update the image like this
let storageRef = Storage.storage().reference(withPath: "/users/\(uid)/profilePhoto.jpg")
storageRef.putData(uploadData, metadata: nil, completion: { (metadata, err) in
If I go to the photo on a new device with no cache yet, it shows the new image. However, if i go to the image on a device that previously viewed it I am left seeing the old image.
EDIT: So I understand the cache works through SDWebImage. I am generating a storage reference to use with SDWebImage based on the users uid. The storage reference is therefore not changing, which is causing the issue.
When you load an image using SDWebImage, it caches the image forever and won't request it from network next time. when you upload a new image from another device the url of the image stays the same i.e. SDWebImage on previous device doesn't know the image has been updated. So you need to come up with an idea on how to notify previous device about the change.
below is how I think it should be done:
When you upload an image use a dynamic picture name. so that the url gets changed thus SDWebImage will load the new profile picture.
In the comments, you asked how would I reference to this dynamic url. You've two possible options(That I can think of):
1) using firebase database: In this we will create a node/reference on database like user/uid. In this we will store the dynamic imageurl with key image. on Any device when yo want to load the image on device you would read the url from the database. It will always point to new image url A nice example on how to do it is on this SO POST
Breif: User-> Upload Image-> Save the Url to Database
Read Picture Url from Firebase -> Load it via SDWebImage UIImageView
2) Using a text file: In this we will not use database. we will create a log file under same folder users/uid/log.txt file. whenever you upload an image to storage we will save the url in this text file and upload it in storage too. When you want to load the image then you first read the text file to get the imageUrl and then load the image using SDWebImage. This way is much similar to uploading and downloading the image file with one additional step that you have to read the text file to get the storage.
Brief: User-> Upload Image -> Put the url in text file and upload it too
Download the text file -> read the image url from file -> load the image via SDWebImage to UIImageVIew
I was reading the docs and found another way. This way you don't need to use dynamic url. you can use your static url. In this you need to query the metadata of the image:
// Create reference to the file whose metadata we want to retrieve
let forestRef = Storage.storage().reference(withPath: "/users/\(uid)/profilePhoto.jpg")
// Get metadata properties
forestRef.getMetadata { metadata, error in
if let error = error {
// Uh-oh, an error occurred!
} else {
// Metadata now contains the metadata for 'profilePhoto.jpg'
}
}
File metadata contains common properties such as name, size, and contentType (often referred to as MIME type) in addition to some less common ones like contentDisposition and timeCreated.
Taken From
Whenever you query metadata save the timeCreated in UserDefaults and next time compare the timeCreated with saved timeCreated if there is difference remove image from SDWebImage Cache and then ask SDWebImage to load the image again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With