我想从应用程序中的多个位置访问nscache,因为我使用它来缓存来自api端点的图像。
例如,下图中的表视图4和视图控制器6使用相同的图像,因此我不想下载它们两次。
候选解决方案:
单重态
class Cache {
private static var sharedCache: NSCache<AnyObject, AnyObject>?
static public func getCache () -> NSCache<AnyObject, AnyObject> {
if sharedCache == nil {
self.sharedCache = NSCache()
}
return sharedCache!
}
}
似乎工作得不错,但“单身汉不好”所以…
将缓存存储在tabviewcontroller中
这会将视图紧密地耦合到视图控制器,因此…
以某种方式存储在appdelegate中。但这和1不一样吗?所以…
使用依赖注入。但是我们在一个tab-view控制器中,所以这和2不一样吗?
我不确定这里的策略是否正确,所以我想问是否还有其他方法可以在这里使用。
我用nscache创建了一个应用程序,并探索了一个单例解决方案。我试着使用依赖注入,但认为它没有意义。我看过堆栈溢出和文档,但是对于这种特定的情况,我没有发现潜在的解决方案。
我给出了一个很小的例子,一个我不满意的图表和测试解决方案。
没有帮助的是说nscache不正确或使用库的答案。我正在尝试使用nscache进行我自己的学习,这不是家庭作业,我想在这个应用程序结构中解决这个问题的具体实例。
问题是如何避免在这个实例中使用单例,即选项卡视图控制器中的视图控制器。
最佳答案
先上来。单身汉并不是天生的坏。它们会使你的代码很难测试,而且它们确实起到了依赖磁铁的作用。
singleton适用于工具类,例如NSFileManager
akaFileManger
,即不携带状态或数据的类。
一个很好的替代方案是依赖注入,但是有了视图控制器和情节串连板,它可能会很难并且感觉非常样板。你最终把所有东西都传给了prepareForSegue
。
一种可能的方法是声明一个描述类缓存接口的protocol
。
protocol CacheProtocol: class {
func doCacheThing()
}
class Cache: CacheProtocol {
func doCacheThing() {
//
}
}
然后声明希望使用此缓存的所有对象都可以使用的
protocol
。protocol CacheConsumer: class {
var cache: CacheProtocol? { get set }
func injectCache(to object: AnyObject)
}
extension CacheConsumer {
func injectCache(to object: AnyObject) {
if let consumer = object as? CacheConsumer {
consumer.cache = cache
}
}
}
最后在顶层创建这个缓存的具体实例。
/// Top most controller
class RootLevelViewController: UIViewController, CacheConsumer {
var cache: CacheProtocol? = Cache()
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
injectCache(to: segue.destination)
}
}
您可以在
prepareForSegue
中将缓存传递到该行。或者可以使用细微的子分类来创建一致性。
class MyTabBarController: UITabBarController, CacheConsumer {
var cache: CacheProtocol?
}
或者您可以使用委托方法来获取向下传播的缓存对象。
extension RootLevelViewController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
injectCache(to: viewController)
}
}
现在有了一个系统,任何
CacheConsumer
都可以使用缓存并将其向下传递到任何其他对象。