Last active
February 7, 2021 06:29
-
-
Save hassanvfx/abfcd543b18eb0c92598ec2e0e40f286 to your computer and use it in GitHub Desktop.
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
class TestModel{ | |
var id = UUID().uuidString | |
} | |
struct TestStruct:Hashable{ | |
var id = UUID().uuidString | |
} | |
let cache = FactoryCache() | |
cache.register { TestModel() } | |
let item:TestModel = cache.fetch( TestStruct() ) | |
let item2:TestModel = cache.fetch( "1234" ) | |
let item3:TestModel = cache.fetch( "1234" ) | |
let item4:TestModel = cache.fetch( "1234" ) | |
print(item.id) | |
print(item2.id) | |
print(item3.id) | |
print(item4.id) |
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
import UIKit | |
public class FactoryCache { | |
public typealias MakerClosure<Item> = ()->Item | |
typealias CacheType = NSCache<NSString, InstanceWrapper> | |
struct CacheWrapper{ | |
var storage: CacheType = NSCache() | |
} | |
struct FactoryWrapper<Item>{ | |
var maker:MakerClosure<Item> | |
} | |
class InstanceWrapper{ | |
var item:Any | |
init(item:Any){ | |
self.item = item | |
} | |
} | |
private var queue = DispatchQueue(label: UUID().uuidString) | |
private var semaphore = DispatchSemaphore(value: 0) | |
private var factories = [Int:Any]() | |
private var caches = [Int: CacheWrapper]() | |
} | |
extension FactoryCache{ | |
public func register<Item>(limit:Int = 99,factory:@escaping MakerClosure<Item>){ | |
queue.async { | |
let key = ObjectIdentifier(Item.self).hashValue | |
let wrapper = FactoryWrapper(maker: factory) | |
let storage = CacheType() | |
let cache = CacheWrapper(storage: storage) | |
storage.countLimit = limit | |
self.factories[key] = wrapper | |
self.caches[key] = cache | |
self.semaphore.signal() | |
} | |
semaphore.wait(timeout: .distantFuture) | |
} | |
} | |
extension FactoryCache{ | |
public func fetch<Keyer:Hashable,Item>(_ item: Keyer) -> Item { | |
var result:Item? | |
queue.async { | |
let key = NSString(string: "\(item.hashValue)") | |
let factoryKey = ObjectIdentifier(Item.self).hashValue | |
guard let cache = self.caches[factoryKey] else { | |
assert(false,"factory not registered") | |
fatalError() | |
} | |
if let wrapper = cache.storage.object(forKey: key) { | |
result = wrapper.item as? Item | |
self.semaphore.signal() | |
return | |
} | |
guard let factory = self.factories[factoryKey] as? FactoryWrapper<Item> else { | |
assert(false,"factory not registered") | |
fatalError() | |
} | |
let instance = factory.maker() | |
cache.storage.setObject(InstanceWrapper(item: instance), forKey: key) | |
result = instance | |
self.semaphore.signal() | |
} | |
semaphore.wait(timeout: .distantFuture) | |
guard let output = result else { | |
assert(false,"failed to build") | |
fatalError() | |
} | |
return output | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment