Skip to content

Instantly share code, notes, and snippets.

Last active June 21, 2022 05:39
What would you like to do?
Using URLCache with download tasks (NSURLCache & NSURLSessionDownloadTask)
import Foundation
import os.log
class URLCacheTest {
let logger = Logger(subsystem: "URLCacheTest", category: "main")
// Date: Wed, 04 Nov 2020 11:13:24 GMT
// Server: Apache
// Strict-Transport-Security: max-age=63072000; includeSubdomains; preload
// X-Content-Type-Options: nosniff
// X-Frame-Options: SAMEORIGIN
// Last-Modified: Sun, 19 May 2002 14:49:00 GMT
// Accept-Ranges: bytes
// Content-Length: 20702285
// Content-Type: application/pdf
let flightPlanURL = URL(string: "")!
// Custom URL cache with 1 GB disk storage
lazy var cache: URLCache = {
let cachesURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
let diskCacheURL = cachesURL.appendingPathComponent("DownloadCache")
let cache = URLCache(memoryCapacity: 100_000_000, diskCapacity: 1_000_000_000, directory: diskCacheURL)"Cache path: \(diskCacheURL.path)")
return cache
// Custom URLSession that uses our cache
lazy var session: URLSession = {
let config = URLSessionConfiguration.default
config.urlCache = cache
return URLSession(configuration: config)
init() {
let documentURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let targetURL = documentURL.appendingPathComponent(flightPlanURL.lastPathComponent)
downloadFile(remoteURL: flightPlanURL, targetURL: targetURL)
func downloadFile(remoteURL: URL, targetURL: URL) {
let request = URLRequest(url: remoteURL)
let downloadTask = session.downloadTask(with: request) { url, response, error in"Download Task complete")
// Store data in cache
if let response = response, let url = url,
self.cache.cachedResponse(for: request) == nil,
let data = try? Data(contentsOf: url, options: [.mappedIfSafe]) {
self.cache.storeCachedResponse(CachedURLResponse(response: response, data: data), for: request)
// Move file to target location
guard let tempURL = url else { return }
_ = try? FileManager.default.replaceItemAt(targetURL, withItemAt: tempURL)
Copy link

ArkadiGiniApps commented Nov 15, 2020

A small side note, using URLSession with background configuration will ignore the URLCache object, its a "minor" not well documented fact. I had it confirmed with a ATS a few years back as far as i know its still there, and very poorly documented

Copy link

Indeed. I mentioned this in the blog post.

Copy link

Thanks for this excellent article and accompanying gist!

Copy link

Hmm doesn’t this defeat the main benefit of a download task, which is to avoid loading the entire file contents into memory?

Copy link

The data is memory mapped, it is not actually loaded into memory. This approach works even for multi-GB-files.

Copy link

Oooh whoops missed the .mappedIfSafe. Thanks, @steipete!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment