Using disk cached images if present in Alamofire Images
Asked Answered
S

1

10

I'm using the AlamofireImage library to cache downloaded images.

Code:

import UIKit
import AlamofireImage

class ViewController: UIViewController {

    @IBOutlet weak var firstImageView: UIImageView!
    @IBOutlet weak var secondImageView: UIImageView!

    let downloader = ImageDownloader()
    let URLRequest = NSURLRequest(URL: NSURL(string: "https://httpbin.org/image/jpeg")!)

    override func viewDidLoad() {
        super.viewDidLoad()
        requestFirstImage()
    }

    func requestFirstImage() {
        downloader.downloadImage(URLRequest: URLRequest) { response in
            print(response.request)
            print(response.response)
            debugPrint(response.result)
            if let image = response.result.value {
                self.firstImageView.image = image
                self.requestSecondImage()
            }
        }
    }

    func requestSecondImage() {
        downloader.downloadImage(URLRequest: URLRequest) { response in
            print(response.request)
            print(response.response)
            debugPrint(response.result)
            if let image = response.result.value {
                self.secondImageView.image = image
            }
        }
    }
}

Log:

enter image description here

As the log shows the first image is requested and the second one is fetched from the cache. No extra request is made and the image shows instantly.

I expect when i re-launch the app that even the first image where fetched from the cache but the Log remains the same. I looked to the Library/Caches/.../fsCachedData and the image is there, ready to be fetched.

Question: What i'm missing here ? I need that the first image get fetched from the disk cache on subsequent requests.

Sexist answered 4/5, 2016 at 23:35 Comment(9)
Have you correctly set the cache-control header on the server?Outspeak
I want to get the locally stored image even if the cache-control header is not settled. If my understanding is correct i should be getting the stored image even when offline. Not the case hereSexist
Then you have to explicitly use AutoPurgingImageCache. Look for an example in the Readme on AlamoFireImage's homepage.Outspeak
ImageDownloader by default uses sets an imageCache using AutoPurgingImageCache. Can you get running the example even when offline loading from disk ?Sexist
Reading the docs, it seem imageCache is an in-memory cache only. Disk caching is only used with NSURLCache. So, to have disk-cached images, you either have to write a disk-cache yourself, or set the cache-control header on the server.Outspeak
ImageDownloader() does disk cache. I can even see there at Library/Caches/..., so is working fine writing the image to disk.Sexist
Let us continue this discussion in chat.Outspeak
The chat link 404s..? What conclusions did you come to?Roeder
@JavierCadiz Did my answer solve your question? Then please mark it as answer!Octavus
O
11

This approach saves the image requests as long on the disk as their cache control max age says and space is available. If you want to set an own max age you have to set up a custom NSURLCache as diskCache where you have to return your modified cachedResponse in the storeCachedResponse method. By the way, the memory cache is handled by the AutoPurgingImageCache in the ImageDownloader. Set up your downloader with this method:

func diskImageDownloader(diskSpaceMB: Int = 150) -> ImageDownloader {

        let diskCapacity = diskSpaceMB * 1024 * 1024
        let diskCache = NSURLCache(memoryCapacity: 0, diskCapacity: diskCapacity, diskPath: "image_disk_cache")
        let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
        configuration.URLCache = diskCache
        let downloader = ImageDownloader(configuration: configuration)
        UIImageView.af_sharedImageDownloader = downloader
        return downloader
    }

Updated on 08/09/16 for @kishorer747:

The NSURLCache memoryCapacity is zero because I don't want image request responses to be saved in cache to save memory. There should only the image be saved for the request url as key by the AutoPurgingImageCache in memory. You can modify my example method as followed to set your desired cacheCapacity and cachePurgeCapacity for the image memory cache:

let cacheCapacity = 100 * 1024 * 1024
let cachePurgeCapacity = 60 * 1024 * 1024
let imageCache: ImageRequestCache = AutoPurgingImageCache(memoryCapacity: cacheCapacity, preferredMemoryUsageAfterPurge: cachePurgeCapacity)
let downloader = ImageDownloader(configuration: configuration, imageCache: imageCache)
Octavus answered 27/7, 2016 at 19:28 Comment(8)
why is memoryCapacity 0? Does this mean you are not caching images in-memory? If i want to , can i specify any size there instead of 0?Blinking
@Blinking I updated my answer for you to show how I would handle the image memory cache.Octavus
i followed your answer to set a disk cache of 20 MB. It works perfectly. But what happens when cache is full? I will be able to still download images using this downloader right? And does it happen like recent images are replaced with the older ones since 20MB limit is reached?Blinking
@Blinking The disk cache is handled by the NSURLCache. Because of that I think random image requests are purged like this answer suggests that the newer image responses can be stored on disk. To change the disk cleaning behavior you have to write your own custom NSURLCache.Octavus
The downloader downloads the images from the web by default if they aren't in the NSURLCache or in the AutoPurgingImageCache anymore.Octavus
thanks. I needed some clarity on this "random image requests are purged if cache gets full". Will look into custom NSURLCacheBlinking
@Octavus Thanks, it helped me as well. However it isn't completely clear for me how I should download images to make them caches. Like Alamofire.request(url).responseImage{ ... } and that's all, or inside the closure I have to add image to the cache manually, like UIImageView.af_sharedImageDownloader.imageCache?.add(...) ? For me only the last option works, however is this the only way ?Maieutic
@Maieutic You can use the normal AlamofireImageView extension to load the images yourImageView.af_setImageWithURL(...). Or if you want to handle it by yourself use UIImageView.af_sharedImageDownloader.downloadImage(URLRequest: request) Here I've posted an example custom NSURLCache https://mcmap.net/q/1165398/-alamofireimage-disk-cache-not-workingOctavus

© 2022 - 2024 — McMap. All rights reserved.