NSCache๋ฅผ ํตํ ๋ฉ๋ชจ๋ฆฌ ์บ์ ๊ตฌํ / ์ ์ฅ ๊ฐฏ์, ์ฉ๋ ์ ํ
์ด๊ธฐ ๊ตฌํ _ ๋จ์ํ NSCache์ ์ ์ฅ
final class ImageCacheManager {
static let shared = ImageCacheManager()
private let cache = NSCache<NSString, UIImage>()
func get(for key: String) -> UIImage? {
cache.object(forKey: key as NSString)
}
func store(_ value: UIImage, for key: String) {
cache.setObject(value, forKey: key as NSString)
}
NSCache์ ๋ํด ์ข ๋ ๊น์ด ํ์ตํ๋ฉฐ ๋ฆฌํฉํฐ๋ง ํ๊ธฐ๋ก ๊ฒฐ์ ํจ
NSLock
์ ์ฌ์ฉํ์ฌ lock, unlock์ ํ๊ธฐ ๋๋ฌธ์ thread safe ํ๋ ๊ฒopen class NSCache<KeyType : AnyObject, ObjectType : AnyObject> : NSObject {
private let _lock = NSLock()
...
open class NSCache<KeyType : AnyObject, ObjectType : AnyObject> : NSObject {
private var _entries = Dictionary<NSCacheKey, NSCacheEntry<KeyType, ObjectType>>()
...
private class NSCacheEntry<KeyType : AnyObject, ObjectType : AnyObject> {
var key: KeyType
var value: ObjectType
var cost: Int
var prevByCost: NSCacheEntry?
var nextByCost: NSCacheEntry?
...
open class NSCache<KeyType : AnyObject, ObjectType : AnyObject> : NSObject {
open func setObject(_ obj: ObjectType, forKey key: KeyType, cost g: Int) {
let g = max(g, 0) // costLimit์ ์ง์ ํ์ง ์์ผ๋ฉด ๊ธฐ๋ณธ์ 0์.
let keyRef = NSCacheKey(key)
fileprivate class NSCacheKey: NSObject {
var value: AnyObject
init(_ value: AnyObject) {
self.value = value
super.init()
}
extension ImageCacheManager: NSCacheDelegate {
func cache(_ cache: NSCache<AnyObject, AnyObject>, willEvictObject obj: Any) {
print("\(obj as? UIImage) ์ ๋ณด๊ฐ ์บ์์์ ์ง์์ง๋ค.")
}
}
open class NSCache<KeyType : AnyObject, ObjectType : AnyObject> : NSObject {
private var _totalCost = 0
open var totalCostLimit: Int = 0 // limits are imprecise/not strict
open var countLimit: Int = 0 // limits are imprecise/not strict
open func setObject(_ obj: ObjectType, forKey key: KeyType) {
setObject(obj, forKey: key, cost: 0)
}
open func setObject(_ obj: ObjectType, forKey key: KeyType, cost g: Int) {
let g = max(g, 0)
...
final class ImageCacheManager {
private let cache = NSCache<NSString, UIImage>()
// ์ด 100๊ฐ ๊น์ง๋ง ์บ์ฑํจ
var countLimit = 100 {
didSet { cache.countLimit = countLimit }
}
// ๋ฉ๋ชจ๋ฆฌ ์บ์ฑ ์์ ์ฉ๋ ์ ์ฝ (๊ธฐ๋ณธ๊ฐ: 200๋ฉ๊ฐ๋ฐ์ดํธ)
var byteLimit: Int = Constants.initialByteLimit {
didSet { cache.totalCostLimit = byteLimit }
}
var megaByteLimit: Int {
get { byteLimit / Constants.megaByteUnit }
set { byteLimit = newValue * Constants.megaByteUnit }
}
func get(for id: UUID) -> UIImage? {
cache.object(forKey: id.uuidString as NSString)
}
func store(_ value: UIImage, for id: UUID) {
let bytesOfImage = value.pngData()?.count ?? 0
cache.setObject(value, forKey: id.uuidString as NSString, cost: bytesOfImage)
}
...