Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase Storage Image Cache not updating SWIFT

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.

like image 599
user6520705 Avatar asked Jun 25 '19 18:06

user6520705


1 Answers

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.

like image 159
Sahil Avatar answered Oct 20 '22 19:10

Sahil