- 1、本文档共5页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
14.2 缓存
14.2 缓存
缓存
如果有很多张图⽚要显⽰,最好不要提前把所有都加载进来,⽽是应该当移出 幕
之后⽴刻销毁。通过选择性的缓存,你就可以避免来回滚动时图⽚重复性的加载了。
缓存其实很简单:就是存储昂贵计算后的结果 (或者是从闪存或者⽹络加载的⽂
件)在内存中,以便后续使⽤,这样访问起来很快。问题在于缓存本质上是⼀个权衡
过程 - 为了提升性能⽽消耗了内存,但是由于内存是⼀个⾮常宝贵的资源,所以不能
把所有东西都做缓存。
何时将何物做缓存 (做多久)并不总是很明显。幸运的是,⼤多情况下,iOS都为
我们做好了图⽚的缓存。
+imageNamed:⽅法
之前我们提到使⽤[UIImage imageNamed:]加载图⽚有个好处在于可以⽴刻解
压图⽚⽽不⽤等到绘制的时候。但是[UIImage imageNamed:]⽅法有另⼀个⾮常
显著的好处:它在内存中⾃动缓存了解压后的图⽚,即使你⾃⼰没有保留对它的任何
引⽤。
对于iOS应⽤那些主要的图⽚ (例如图标,按钮和背景图⽚),使⽤[UIImage
imageNamed:]加载图⽚是最简单最有效的⽅式。在nib⽂件中引⽤的图⽚同样也是
这个机制,所以你很多时候都在隐式的使⽤它。
但是[UIImage imageNamed:]并不适⽤任何情况。它为⽤户界⾯做了优化,但
是并不是对应⽤程序需要显⽰的所有类型的图⽚都适⽤。有些时候你还是要实现⾃⼰
的缓存机制,原因如下:
[UIImage imageNamed:]⽅法仅仅适⽤于在应⽤程序资源束⽬录下的图
⽚,但是⼤多数应⽤的许多图⽚都要从⽹络或者是⽤户的相机中获取,所以
[UIImage imageNamed:]就没法⽤了。
[UIImage imageNamed:]缓存⽤来存储应⽤界⾯的图⽚ (按钮,背景等
等)。如果对照⽚这种⼤图也⽤这种缓存,那么iOS系统就很可能会移除这些
图⽚来节省内存。那么在切换页⾯时性能就会下降,因为这些图⽚都需要重新
加载。对传送器的图⽚使⽤⼀个单独的缓存机制就可以把它和应⽤图⽚的⽣命
周期解耦。
[UIImage imageNamed:]缓存机制并不是公开的,所以你不能很好地控制
它。例如,你没法做到检测图⽚是否在加载之前就做了缓存,不能够设置缓存
⼤⼩,当图⽚没⽤的时候也不能把它从缓存中移除。
⾃定义缓存
构建⼀个所谓的缓存系统⾮常困难。菲尔 卡尔顿曾经说过:“在计算机科学中只有
两件难事:缓存和命名” 。
如果要写⾃⼰的图⽚缓存的话,那该如何实现呢?让我们来看看要涉及哪些⽅⾯:
选择⼀个合适的缓存键 - 缓存键⽤来做图⽚的唯⼀标识。如果实时创建图⽚,
通常不太好⽣成⼀个字符串来区分别的图⽚。在我们的图⽚传送带例⼦中就很
简单,我们可以⽤图⽚的⽂件名或者表格索引。
提前缓存 - 如果⽣成和加载数据的代价很⼤,你可能想当第⼀次需要⽤到的时
候再去加载和缓存。提前加载的逻辑是应⽤内在就有的,但是在我们的例⼦
中,这也⾮常好实现,因为对于⼀个给定的位置和滚动⽅向,我们就可以精确
地判断出哪⼀张图⽚将会出现。
缓存失效 - 如果图⽚⽂件发⽣了变化,怎样才能通知到缓存更新呢?这是个⾮
常困难的问题 (就像菲尔 卡尔顿提到的),但是幸运的是当从程序资源加载静
态图⽚的时候并不需要考虑这些。对⽤户提供的图⽚来说 (可能会被修改或者
覆盖),⼀个⽐较好的⽅式就是当图⽚缓存的时候打上⼀个时间戳以便当⽂件
更新的时候作⽐较。
缓存回收 - 当内存不够的时候,如何判断哪些缓存需要清空呢?这就需要到你
写⼀个合适的算法了。幸运的是,对缓存回收的问题,苹果提供了⼀个叫
做NSCache通⽤的解决⽅案
NSCache
NSCache和NSDictionary类似。你可以通过-setObject:forKey :和-
object:forKey :⽅法分别来插⼊,检索。和字典不同的是,NSCache在系统低内
存的时候⾃动丢弃存储的对象。
NSCache⽤来判断何时丢弃对象的算法并没有在⽂档中给出,但是你可以使⽤-
setCo ntLimit:⽅法设置缓存⼤⼩,以及-se
文档评论(0)