Caching in Swift (iOS/macOS): Redis and Other Tools
Caching is one of the key strategies for optimizing the performance of mobile and desktop applications in Swift. It allows you to reduce data loading time, decrease network and server load, and ensure the application works in offline mode. The Apple ecosystem offers both built-in mechanisms (NSCache, URLCache) and third-party solutions, including integration with Redis. In this article, we will thoroughly examine the main caching tools for iOS and macOS with code examples.
1. Built-in Caching Mechanisms in Foundation
NSCache — Lightweight In-Memory Cache
NSCache is a thread-safe, automatically managed cache that removes objects when memory is low. It is ideal for temporarily storing images, model data, or computation results.
import Foundation
let imageCache = NSCache<NSString, UIImage>()
// Setting limitsimageCache.countLimit = 100 // Maximum 100 objectsimageCache.totalCostLimit = 50 * 1024 * 1024 // 50 MB
// Savingfunc cacheImage(_ image: UIImage, forKey key: String) { imageCache.setObject(image, forKey: key as NSString, cost: image.size.width * image.size.height * 4)}
// Retrievingfunc getCachedImage(forKey key: String) -> UIImage? { return imageCache.object(forKey: key as NSString)}Advantages: simplicity, automatic cleanup, support for object cost.
Disadvantages: in-memory only, no persistence.
URLCache — HTTP Request Caching
URLCache automatically caches URLSession responses. It works both in memory and on disk. It can be configured globally or for a specific session.
import Foundation
// Configuring a cache with 50 MB memory and 100 MB disklet cache = URLCache(memoryCapacity: 50 * 1024 * 1024, diskCapacity: 100 * 1024 * 1024, diskPath: "myCache")URLCache.shared = cache
// Usage with URLSessionlet config = URLSessionConfiguration.defaultconfig.urlCache = cacheconfig.requestCachePolicy = .returnCacheDataElseLoadlet session = URLSession(configuration: config)
let request = URLRequest(url: URL(string: "https://api.example.com/data")!)let task = session.dataTask(with: request) { data, response, error in // Data will be automatically cached}task.resume()Cache policy management is done via Cache-Control server headers or requestCachePolicy.
2. File Caching for Offline Access
When data needs to be preserved between application launches, file caching in the Caches directory is used. It is convenient for JSON, images, or serialized objects.
import Foundation
class FileCache { private let fileManager = FileManager.default private lazy var cacheDirectory: URL = { let paths = fileManager.urls(for: .cachesDirectory, in: .userDomainMask) return paths[0].appendingPathComponent("DataCache", isDirectory: true) }() init() { try? fileManager.createDirectory(at: cacheDirectory, withIntermediateDirectories: true) } func save(data: Data, forKey key: String) { let fileURL = cacheDirectory.appendingPathComponent(key) try? data.write(to: fileURL) } func load(forKey key: String) -> Data? { let fileURL = cacheDirectory.appendingPathComponent(key) return try? Data(contentsOf: fileURL) } func clearAll() { try? fileManager.removeItem(at: cacheDirectory) try? fileManager.createDirectory(at: cacheDirectory, withIntermediateDirectories: true) }}