Created
May 4, 2017 19:03
-
-
Save mohamede1945/8816d49a87000ffd02e8fda97e5d242c to your computer and use it in GitHub Desktop.
NSCache wrapper that works with Swift structs
This file contains hidden or 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
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") |
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
Great stuff!
Bug - set { cache.totalCostLimit = totalCostLimit } should be set { cache.totalCostLimit = newValue }
Cheers!