# Image Caching in SwiftUI

Caching images is an important technique for optimizing the performance of your SwiftUI app. When you load an image, it can take time to fetch it from a remote server or read it from disk. By caching the image, you can avoid repeating this time-consuming process every time the image is needed. In this blog post, we'll explore how to cache images in SwiftUI.

The code in this post is available [here](https://github.com/xavier7t/iOSDevX/tree/main/iOSDevX/202304-Apr%202023/Image%20Caching).

### **Using Image Cache**

One way to cache images in SwiftUI is to create an `ImageCache` class. This class can store a cache of `UIImage` objects, and it can be accessed from any part of your app. Here's an example of how you can create an `ImageCache` class:

```swift
class ImageCache {
    static let shared = ImageCache()

    private let cache = NSCache<NSString, UIImage>()

    private init() {}

    func set(_ image: UIImage, forKey key: String) {
        cache.setObject(image, forKey: key as NSString)
    }

    func get(forKey key: String) -> UIImage? {
        return cache.object(forKey: key as NSString)
    }
}
```

In this example, we've created a singleton `ImageCache` object using the `shared` property. The `cache` property is an `NSCache` object that stores `UIImage` objects, and we've defined `set(_:,forKey:)` and `get(forKey:)` methods to add and retrieve images from the cache.

### **Caching Images with URL**

Another common use case for caching images in SwiftUI is when loading images from a remote server. In this case, you can use the `dataTask(with:completionHandler:)` method of the `URLSession` API to load the image data asynchronously. Once the image data is loaded, you can cache it using the `ImageCache` class.

```swift
struct RemoteImage: View {
    @ObservedObject var imageLoader: ImageLoader

    init(url: String) {
        imageLoader = ImageLoader(url: url)
    }

    var body: some View {
        if let image = imageLoader.image {
            Image(uiImage: image)
                .resizable()
        } else {
            ProgressView()
        }
    }
}

class ImageLoader: ObservableObject {
    @Published var image: UIImage?

    private var url: String
    private var task: URLSessionDataTask?

    init(url: String) {
        self.url = url
        loadImage()
    }

    private func loadImage() {
        if let cachedImage = ImageCache.shared.get(forKey: url) {
            self.image = cachedImage
            return
        }

        guard let url = URL(string: url) else { return }

        task = URLSession.shared.dataTask(with: url) { data, response, error in
            guard let data = data, error == nil else { return }

            DispatchQueue.main.async {
                let image = UIImage(data: data)
                self.image = image
                ImageCache.shared.set(image!, forKey: self.url)
            }
        }
        task?.resume()
    }
}
```

In this example, we've created a `RemoteImage` view that loads an image from a remote server using the `ImageLoader` class. The `ImageLoader` class is an `ObservableObject` that uses the `dataTask(with:completionHandler:)` method to load the image data asynchronously. We've also added a check for cached images using the `ImageCache` class, which avoids fetching the image from the remote server if it's already cached.

Note: To validate the implementation above, you can use the image from the project iOSDevX with the URL: "[https://github.com/xavier7t/iOSDevX/blob/main/iOSDevX/Assets.xcassets/demo.imageset/demo.png?raw=true](https://github.com/xavier7t/iOSDevX/blob/main/iOSDevX/Assets.xcassets/demo.imageset/demo.png?raw=true)". You can write a simple SwiftUI View like the one below:

```swift
struct ContentView: View {
    let urlString = "https://github.com/xavier7t/iOSDevX/blob/main/iOSDevX/Assets.xcassets/demo.imageset/demo.png?raw=true"
    var body: some View {
        VStack {
            RemoteImage(url: urlString)
                .frame(width: 150, height: 150, alignment: .center)
                .cornerRadius(10)
        }
    }
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1681877607129/461dd138-5a55-4302-9c8b-8c22441c1f1d.png align="center")

# **Conclusion**

Caching images is an important technique for optimizing the performance of your SwiftUI app. By creating an `ImageCache` class and using it to cache images, you can avoid repeating time-consuming image-loading operations.

And that’s all of today’s post. I hope it helps and let me know if it is by leaving a comment. Don’t forget to subscribe to my newsletter if you’d like to receive posts like this via email.

I’ll see you in the next post!
