Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@mohamede1945
Created May 4, 2017 19:03
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mohamede1945/8816d49a87000ffd02e8fda97e5d242c to your computer and use it in GitHub Desktop.
Save mohamede1945/8816d49a87000ffd02e8fda97e5d242c to your computer and use it in GitHub Desktop.
NSCache wrapper that works with Swift structs
private class ObjectWrapper {
let value: Any
init(_ value: Any) {
self.value = value
}
}
private class KeyWrapper<KeyType: Hashable>: NSObject {
let key: KeyType
init(_ key: KeyType) {
self.key = key
}
override var hash: Int {
return key.hashValue
}
override func isEqual(_ object: Any?) -> Bool {
guard let other = object as? KeyWrapper<KeyType> else {
return false
}
return key == other.key
}
}
open class Cache<KeyType: Hashable, ObjectType> {
private let cache: NSCache<KeyWrapper<KeyType>, ObjectWrapper> = NSCache()
public init(lowMemoryAware: Bool = true) {
guard lowMemoryAware else { return }
NotificationCenter.default.addObserver(
self,
selector: #selector(onLowMemory),
name: .UIApplicationDidReceiveMemoryWarning,
object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
@objc private func onLowMemory() {
removeAllObjects()
}
open var name: String {
get { return cache.name }
set { cache.name = newValue }
}
weak open var delegate: NSCacheDelegate? {
get { return cache.delegate }
set { cache.delegate = newValue }
}
open func object(forKey key: KeyType) -> ObjectType? {
return cache.object(forKey: KeyWrapper(key))?.value as? ObjectType
}
open func setObject(_ obj: ObjectType, forKey key: KeyType) { // 0 cost
return cache.setObject(ObjectWrapper(obj), forKey: KeyWrapper(key))
}
open func setObject(_ obj: ObjectType, forKey key: KeyType, cost: Int) {
return cache.setObject(ObjectWrapper(obj), forKey: KeyWrapper(key), cost: cost)
}
open func removeObject(forKey key: KeyType) {
return cache.removeObject(forKey: KeyWrapper(key))
}
open func removeAllObjects() {
return cache.removeAllObjects()
}
open var totalCostLimit: Int {
get { return cache.totalCostLimit }
set { cache.totalCostLimit = totalCostLimit }
}
open var countLimit: Int {
get { return cache.countLimit }
set { cache.countLimit = newValue }
}
open var evictsObjectsWithDiscardedContent: Bool {
get { return cache.evictsObjectsWithDiscardedContent }
set { cache.evictsObjectsWithDiscardedContent = newValue }
}
}
// ************************************************************
// Test Example
let cache = Cache<String, Int>()
cache.setObject(2, forKey: "aa")
cache.object(forKey: "aa")
cache.object(forKey: "B")
cache.setObject(12, forKey: "B")
cache.object(forKey: "B")
@TosinAF
Copy link

TosinAF commented Jan 3, 2019

Great stuff!

Bug - set { cache.totalCostLimit = totalCostLimit } should be set { cache.totalCostLimit = newValue }

Cheers!

@Stitch7
Copy link

Stitch7 commented Jul 22, 2021

4 years old gist, but because it's the first google result for "swift nscache wrapper" (at least for me). Observing UIApplicationDidReceiveMemoryWarning is unnecessary, because NSCache does that internally (that's the whole point over NSDictionary) and it does that by only evicting as much entries as needed and not clearing everything like here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment