swift - 在选项卡视图控制器中跨视图控制器访问 NSCache
问题描述
我想从我的应用程序中的多个位置访问 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一样吗?所以...
使用依赖注入。但是我们在一个选项卡视图控制器中,所以这不是和 2 一样吗?
我不确定这里的策略是否正确,所以我问这里是否可以使用另一种方法。
我所做的使用 NSCache 创建了一个带有示例的应用程序,并探索了一个单例解决方案。我尝试使用依赖注入,但认为它没有意义。我查看了堆栈溢出和文档,但对于这种特定情况,我没有发现潜在的解决方案。
我给出的一个最小的例子,带有一个我不满意的图表和经过测试的解决方案。
没有帮助的是说 NSCache 不正确或使用库的答案。我正在尝试将 NSCache 用于我自己的学习,这不是家庭作业,我想在这个 App 结构中解决这个问题的这个特定实例。
问题是如何避免在这种情况下使用单例,在选项卡视图控制器中查看控制器。
解决方案
第一。单身人士并不是天生就不好。它们会使您的代码难以测试,并且它们确实起到了依赖磁铁的作用。
单例适用于作为工具的类,例如NSFileManager
aka FileManger
,即不携带状态或数据的东西。
一个很好的替代方案是依赖注入,但是对于视图控制器和情节提要,它可能很难并且感觉非常样板。您最终将所有内容传递到prepareForSegue
.
一种可能的方法是声明一个protocol
描述类似缓存的接口的 a。
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
都可以使用缓存并将其向下传递给任何其他对象。
推荐阅读
- python - Flask 从 nginx 实例运行 bash 命令
- r - 我可以使用 Rcpp 加速我的 R 代码吗?
- jdbc - Jaybird 中的 Firebird NUMERIC/DECIMAL 精度和比例
- c# - 为什么在实现 AsyncCache 时需要对 Task 进行延迟包装?
- python - 将列连接成日期
- mysql - 用于 python 3.7 的 MySQL 包
- http - 停止服务器而不退出程序 golang
- javascript - Javascript 执行顺序 - window.location.href 何时发生?
- laravel - 如何在此二进制推荐系统中插入位置 ID
- javascript - nodejs express 在另一个文件中重用路由获取方法