Last active
August 21, 2024 11:18
-
-
Save steipete/a7b46f36bc1a341bfe26897d964169af to your computer and use it in GitHub Desktop.
Using URLCache with download tasks (NSURLCache & NSURLSessionDownloadTask)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import os.log | |
class URLCacheTest { | |
let logger = Logger(subsystem: "URLCacheTest", category: "main") | |
// HTTP HEADERS: | |
// 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: "https://www.hq.nasa.gov/alsj/a17/A17_FlightPlan.pdf")! | |
// 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) | |
logger.info("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 | |
self.logger.info("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) | |
} | |
downloadTask.resume() | |
} | |
} |
It’s been 5 years since this - I would not assume any of this is still accurate. This needs a re-test. I don’t do iOS work these days, so someone else could pick this up.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
HI @steipete, thanks for great article 👏 I'm wondering about on thing. In line 48 you check if doesn't have entry for given request, but what if we already had old version of response cached and we want to substitute it with the recent one? Is it guaranteed that
URLSession
removes old data before invoking completion?