可怜的 NSCache
一直处于 NSMutableDictionary
的阴影之下。就好像没有人知道它提供了垃圾处理的功能,而开发者们却费劲力气地去自己实现它。
没错,NSCache
基本上就是一个会自动移除对象来释放内存的 NSMutableDictionary
。无需响应内存警告或者使用计时器来清除缓存。唯一的不同之处是键对象不会像 NSMutableDictionary
中那样被复制,这实际上是它的一个优点(键不需要实现 NSCopying
协议)。
如果开发者们知道就好了……
但是,你并不像其他开发者那样,对吧?你应该不会小看 NSCache
的?
这并不是说它没有一丝瑕疵和一些莫名其妙的问题。NSCache
就像是个烫手山芋。
拿 setObject:forKey:cost:
来说,它和 setObject:forKey:
方法类似,但是带着 cost
参数。你可能会问,那是个什么东西?好吧,官方文档甚至都没有说清楚:
cost
被用来计算缓存中所有对象的代价。当内存受限或者所有缓存对象的总代价超过了最大允许的值时,缓存会移除其中的一些对象。
很好,目前为止还不错……
然而,这个移除流程并不会保证顺序。后果就是,如果你期望通过控制
cost
的值来完成某些特殊行为的话,结果可能会对你的程序无益。
啊?这是什么意思?
通常,精确的
cost
应该是对象占用的字节数。如果它不可以直接读出来的话,你没必要费劲地去计算它,因为这么做的话会增加使用缓存的代价。
等会儿,那不精确的 cost
值应该怎么计算呢?有什么计算内存占用的规则吗?比如按数量排序来计算?“随便瞎猜导致性能变差”似乎不会让人满意……
如果你没有有效的值传入,那就传入 0,或者用 setObject:forKey: 方法,它不需要传入
cost
值。
懂了:除非你在 Apple 工作并且认识写这个类的人,否则不要用这个方法。
另外,它还有一套使用 evictsObjectsWithDiscardedContent
和 <NSDiscardableContent>
来控制对象是否会被自动移除的机制,但是这可能只会让你碰到更多的问题。
尽管有上面提到的这些问题,开发者们还是应该多多使用 NSCache
。你项目中任何你称之为缓存却不是 NSCache
对象的东西都应该被换成 NSCache
。但是,如果你这么做了,务必要用你熟悉的那套 objectForKey:
、setObject:forKey:
、removeObjectForKey:
方法。
除非另有声明,本文采用知识共享「署名-非商业性使用 3.0 中国大陆」许可协议授权。