URLCache (CS193P Assignment 6)

846 Views Asked by At

I'm now on Stanford iOS Swift Assignment 6 where one of the required tasks is to use URLCache to cache the image on the local disk. After days of googling, I still couldn't figure out how to use it. It'd be helpful if anyone could point me to a good guide!

My code is like this now after trying to understand the official documentation. It doesn't help that the official doc doesn't have sample codes I could refer to :(

let urlCache = URLCache.shared

The required task is to set a cache and specify the size limit. I tried initialising URLCache and pass the size in the parameters. It works but storing and getting the cache doesn't seem to work. If URLCache is initialised every time the app (or view controller) is launched, wouldn't it ignore the previous cache that was created and stored?

I think there's no issue with this code? reading data from cache

if let cachedURLResponse = urlCache.cachedResponse(for: URLRequest(url: url)) {
    if let fetchedImage = UIImage(data: cachedURLResponse.data) {
        image = fetchedImage
    }
}

I'm lost on writing data to cache

urlCache.storeCachedResponse(CachedURLResponse(response: URLResponse(), data: imageData), for: URLRequest(url: url))

How to initialise URLResponse properly? I looked at the init method and it also requires url to be passed in as parameter. Found this strange since url is in URLRequest() too. Am I doing it wrong?

Helpful advice much appreciated!

1

There are 1 best solutions below

1
David Steppenbeck On BEST ANSWER

You can use URLCache by making a request for the image data with URLSession then using the data and response available in its completion handler, for example:

import UIKit

class GalleryCollectionViewController: UICollectionViewController, UICollectionViewDragDelegate, UICollectionViewDropDelegate, UICollectionViewDelegateFlowLayout {

 // MARK: - Model

 var gallery: Gallery?

 // MARK: - Properties

 private var cache = URLCache.shared
 private var session = URLSession(configuration: .default)

 override func viewDidLoad() {
    super.viewDidLoad()
    cache = URLCache(memoryCapacity: 100, diskCapacity: 100, diskPath: nil) // replace capacities with your own values
 }

 override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "GalleryCell", for: indexPath)
    if let galleryCell = cell as? GalleryCollectionViewCell {
        galleryCell.image = nil
        galleryCell.imageView.isHidden = true
        if let url = gallery?.images[indexPath.item].url {
            let request = URLRequest(url: url.imageURL) // imageURL from Utilities.swift of Stanford iOS course
            if let cachedResponse = cache.cachedResponse(for: request), let image = UIImage(data: cachedResponse.data) {
                galleryCell.image = image
                galleryCell.imageView.isHidden = false
            } else {
                DispatchQueue.global(qos: .userInitiated).async { [weak self, weak galleryCell] in
                    let task = self?.session.dataTask(with: request) { (urlData, urlResponse, urlError) in
                        DispatchQueue.main.async {
                            if urlError != nil { print("Data request failed with error \(urlError!)") }
                            if let data = urlData, let image = UIImage(data: data) {
                                if let response = urlResponse {
                                    self?.cache.storeCachedResponse(CachedURLResponse(response: response, data: data), for: request)
                                }
                                galleryCell?.image = image
                            } else {
                                galleryCell?.image = UIImage(named: "placeholder")
                            }
                            galleryCell?.imageView.isHidden = false
                        }
                    }
                    task?.resume()
                }
            }
        }
    }
    return cell
 }
}