Created
September 29, 2019 11:47
-
-
Save LukeSmith16/f83387c6cb2afbc11017c8f51577494e to your computer and use it in GitHub Desktop.
A thin wrapper around NSCache
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
/// Removes stale objects after 12 hours. | |
final class Cache<Key: Hashable, Value> { | |
private let wrapped = NSCache<WrappedKey, Entry>() | |
private let dateProvider: () -> Date | |
private let entryLifetime: TimeInterval | |
init(dateProvider: @escaping () -> Date = Date.init, | |
entryLifetime: TimeInterval = 12 * 60 * 60) { | |
self.dateProvider = dateProvider | |
self.entryLifetime = entryLifetime | |
} | |
func insert(_ value: Value, forKey key: Key) { | |
let date = dateProvider().addingTimeInterval(entryLifetime) | |
let entry = Entry(value: value, expirationDate: date) | |
wrapped.setObject(entry, forKey: WrappedKey(key)) | |
} | |
func value(forKey key: Key) -> Value? { | |
guard let entry = wrapped.object(forKey: WrappedKey(key)) else { | |
return nil | |
} | |
guard dateProvider() < entry.expirationDate else { | |
removeValue(forKey: key) | |
return nil | |
} | |
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 { | |
guard let value = newValue else { | |
removeValue(forKey: key) | |
return | |
} | |
insert(value, 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 | |
let expirationDate: Date | |
init(value: Value, expirationDate: Date) { | |
self.value = value | |
self.expirationDate = expirationDate | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment