Skip to content

Instantly share code, notes, and snippets.

@lipka
Last active November 26, 2023 00:50
Show Gist options
  • Save lipka/abfff806c3e494320c7e73004e348dce to your computer and use it in GitHub Desktop.
Save lipka/abfff806c3e494320c7e73004e348dce to your computer and use it in GitHub Desktop.
A first-class type-safe Swift cache based on NSCache with support for value types as keys.
import Foundation
// Based on https://www.swiftbysundell.com/articles/caching-in-swift/
final class Cache<Key: Hashable, Value> {
private let wrapped = NSCache<WrappedKey, Entry>()
func insert(_ value: Value, forKey key: Key) {
let entry = Entry(value: value)
wrapped.setObject(entry, forKey: WrappedKey(key))
}
func value(forKey key: Key) -> Value? {
let entry = wrapped.object(forKey: WrappedKey(key))
return entry?.value
}
func removeValue(forKey key: Key) {
wrapped.removeObject(forKey: WrappedKey(key))
}
}
extension Cache {
subscript(key: Key) -> Value? {
get {
return value(forKey: key)
}
set {
if let value = newValue {
insert(value, forKey: key)
} else {
removeValue(forKey: key)
}
}
}
}
private extension Cache {
final class WrappedKey: NSObject {
let key: Key
init(_ key: Key) { self.key = key }
override var hash: Int { return key.hashValue }
override func isEqual(_ object: Any?) -> Bool {
guard let value = object as? WrappedKey else {
return false
}
return value.key == key
}
}
}
private extension Cache {
final class Entry {
let value: Value
init(value: Value) {
self.value = value
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment