Cache is a Swift library for caching Identifiable
values with optional expiry logic. It supports both in-memory and file-backed storage, making it suitable for short-lived data, offline persistence, or resource caching.
- ✅ Type-safe caching for any
Identifiable
type - 📦 Two interchangeable storage implementations:
VolatileCache
: fast in-memory storageFileSystemCache
: persistent, file-backed storage
- 💡 Expiry support:
.short
or.custom(Date)
- 🧪 Testable without delays (no need for
sleep
) - 🕹 Native async/await support. Fully thread safe and sendable.
- 🧩 Easily injectable via
swift-dependencies
See the QuickStart guide in the Documentation.docc
catalogue.
struct Cheese: Identifiable {
let id: Int
let name: String
}
let cache = VolatileCache<Cheese>()
try await cache.stash(Cheese(id: 0, name: "Brie"), duration: .short)
An example using swift-dependencies
.
import Dependencies
import Cache
extension DependencyValues {
/// A cache for storing and retrieving `Cheese` models.
var cheeseCache: any Cache<Cheese> {
get { self[CheeseCacheKey.self] }
set { self[CheeseCacheKey.self] = newValue }
}
}
private enum CheeseCacheKey: DependencyKey {
static let liveValue: any Cache<Cheese> = FileSystemCache(.caches, subfolder: "Cheeses")
}
Then use it like this:
struct MyModel {
@Dependency(\.cheeseCache) var cheeseCache
fucn loadCheese(id: Int) throws -> Cheese? {
try await cheeseCache.resource(for: id)
}
}
#Preview {
withDependencies {
$0.cheeseCache = MockCache()
} operation: {
ContentView()
}
}
private actor MockCache: Cache {
private var store: [Int: Cheese] = [:]
func stash(_ item: Cheese, duration: Expiry) async throws {
// Ignore `duration` for now; just stash in memory
store[item.id] = item
}
func removeResource(for identifier: Int) async throws {
store.removeValue(forKey: identifier)
}
func resource(for identifier: Int) async throws -> Cheese? {
store[identifier]
}
func reset() async throws {
store.removeAll()
}
}