The reason why your cache isn't refreshing is because you're always writing to the same path, you're just uploading a different image. I see you've been asking about creating a dynamic URL which will, in theory, create an image path that's not cached and therefore reload correctly.
But you don't need to do that. I had the same case and issue recently while working on an app that used Firebase. I had a player model which contained within itself a reference to the profile picture. The picture was stored using Firebase Storage and the folder path was /players/\(uid)/profilePhoto.jpg
. The profile picture could be changed both by purchasing an avatar and using the camera to snap a photo. And since I was uploading to the same storage path every time, my image wasn't reloading either.
Now, SDWebImage cache is automatic - unless you specify differently, whenever you call someImageView.sd_setImage(with: imageUrl)
the URL is cached via SDImageCache.
So all I do is delete the image from the cache whenever I get a new reference - in the didSet
property observer of the profile picture.
/// property to store the profile picture url
internal var profilePictureUrl: String = "" {
didSet {
SDImageCache.shared().removeImage(forKey: Storage.storage().reference().child(profilePicture).fullPath, withCompletion: nil)
}
}
Now, every time the property is set, the url is deleted from cache and SDWebImage has to fetch it again. It does so when you call sd_setImage(with: imageUrl)
and caches it again.
/// public property to set the profile image on the button
internal var profileImagePath: String? {
didSet {
if let path = profileImagePath {
profileButton.imageView?.sd_setImage(with: Storage.storage().reference().child(path), placeholderImage: nil, completion: { [weak self] (image, error, _, _) in
self?.profileButton.setImage(image ?? #imageLiteral(resourceName: "default-profile-pic"), for: .normal)
})
}
}
}
I have a button that displays my profile picture in its image view. When I get the new image and call a method to refresh the button's view the image is fetched and since the cache doesn't have a reference to the image path anymore, it'll fetch the newly uploaded image and recreate the cache path.
That's how I made this work for me. I hope that it solves your issue, as well. Feel free to ask for any additional clarifications and I will do my best to answer.
Edit: Sahil Manchanda pointed out to me that I'd misunderstood the full scope of the question.
My answer will work best on a single device.
If the issue is multiple device synchronisation you can still use the offered solution but with some more frequent UI updates - since the profilePictureUrl
property gets updated every time the user's info is fetched from Firebase, the update may be delayed until the next time the user's info is read or the app is restarted.
You can also add a connectivity check before deleting the cache to avoid any losses caused by laggy bandwidth.
Another solution could be the use of silent notifications (meant for quick refresh operations) which will just serve as a "reminder" to the device that it's time to clear the cache. You can use Firebase's Cloud Messaging if you don't have any experience with servers or OneSignal.