SDWebImageSwiftUI - Image Loading and Caching

1.4k Views Asked by At

I'm working on developing an image heavy iOS app:

  • Users upload images to the app, all of which are then added to a cloud storage bucket. A database entry is also created, which contains the url to the image's location in the cloud storage bucket.
  • The SDWebImageSwiftUI framework is used to load the user's images (that are in the cloud storage bucket) into the app and display them.

When a user signs into their account or when a user launches the app and they are already authenticated, a "loading" screen appears while the rest of their account information is retrieved from a database. Part of the information that is collected from the database includes a url to each of the user's uploaded images. Once the app receives these urls (and while the "loading" screen is still on display), I load in the images. Once all the information has been received from the database and once all the images are preloaded, the "loading" screen disappears, taking the user into the app, where the images are displayed right away. I set it up this way so that when the user is taken into the "normal" app screens, they don't have to wait again for the images to load and populate into the view. Below you will find the code that I use to preload these images.

import Foundation
import SDWebImageSwiftUI

// used to retrieve and collect all information relating to a user and their account
class SessionStore: ObservableObject {
    @Published var user: User?
    @Published var collections: [Collection]?
    
    // ...
    
    // called after a user's collections have been retrieved from the database
    func preloadImages() {
        guard let collections = self.collections else { return }
        
        // each collection object / item has an image associated with it, so iterate through all of the user's collections
        for collection in collections {
            // load the collection's image 
            let imageManager = ImageManager(url: URL(string: collection.imageUrl))
            imageManager.load()
        }
    }
}

The SDWebImageSwiftUI framework has caching capabilities, but I am not currently taking advantage of them as I don't feel confident in my understanding of the subject and cannot find much information online. I am hoping that someone will be able to please explain this more in depth to me and potentially give me some recommendations? Some of my questions are detailed below:

  • Should I use a cache in my app since it so heavily relies on images?
  • How can I set up and use SDWebImageSwiftUI's cache systems? What are some good guidelines / principles for configuring a cache system (i.e., memory and disk size)?
  • When does a SDWebImageSwiftUI cache system reset, if ever?
  • If I add a cache system, would that help images load faster? Would I be able to remove the image "preloading" functionality I detailed above?

Additionally, I've noticed that if the app moves to the background and then later reenters the foreground, the images are being reloaded. So any images that were being displayed on the user's last screen, temporarily disappear when the app first opens back up. In this case, the "preloading" functionality that I detailed above is not triggered to run. Rather, the images are loaded in due to their presence in the view (see below code), meaning that only the images on the one screen are loaded back in. If I then navigate to another app screen, the images again won't be preloaded and will load as / if they are presented in the view.

import SwiftUI
import SDWebImageSwiftUI

struct ExampleView: View {
    @EnvironmentObject var session: SessionStore
    
    let threeColumnGrid = [GridItem(.fixed(UIScreen.main.bounds.width * 0.28)), GridItem(.fixed(UIScreen.main.bounds.width * 0.28)), GridItem(.fixed(UIScreen.main.bounds.width * 0.28))]
    
    var body: some View {
        ScrollView(.vertical, showsIndicators: false) {
            LazyVGrid(columns: threeColumnGrid, alignment: .center, spacing: 10) {
                ForEach(session.collections ?? [], id: \.collectionId) { (collectionItem) in
                    // when the app enters the foreground after being in the background, the images are no longer preloaded into the app
                    // so instead of seeing an image displayed within a rounded rectangle (as expected), the user will see an empty rounded rectangle as the image reloads
                    // the following line is what seems to be triggering the image to be loaded again
                    WebImage(url: URL(string: collectionItem.imageUrl))
                        .resizable()
                        .scaledToFit()
                        .padding(.vertical, 5)
                        .padding(.horizontal, 10)
                        .frame(width: UIScreen.main.bounds.width * 0.28, height: UIScreen.main.bounds.height * 0.22)
                        .background(
                            RoundedRectangle(cornerRadius: 10)
                                .stroke(Color.black.opacity(0.5), lineWidth: 1)
                        )
                } // ForEach
            } // LazyVGrid
            .padding(.top, 2)
        } // ScrollView
    }
}

I am also wondering if a cache would help resolve these image "loading lags" when the app renters the foreground? As I believe the cache would have a loaded version of the image, which can be accessed and displayed quicker?

Any knowledge on SDWebImageSwiftUI's caching capabilities, would be greatly appreciated!

0

There are 0 best solutions below