iOS - 保存图片的最佳实践 - NSCache与保存在文档目录中的比较

21

我正在开发一个类似Instagram feed的应用程序(使用表格视图来展示包含图像和一些标签的单元格)。

对于从数据库中获取的所有数据,我都使用Data Task(因为接收它们不需要花费太多时间),但是对于图像(它们的url是通过Data请求获取的),我需要将其本地保存以备将来使用(以改善用户体验)。

我的逻辑如下: 将图像保存在NSCache或Document Directory中,放到一个具有其下载日期的文件夹内(仅创建一次并添加所有其他图像)(我会删除非最近7天的所有文件夹),然后对于TableView,只需从那里加载即可,这样TableView会平滑滚动,并且不会直接从其委托方法中加载url。 因此,根据我的需求,何处更好地存储它们,NSCache还是Document Directory

期待您的建议,谢谢!


SDWebImage 可能会解决您的问题。它可以将图像缓存在磁盘中。NSCache可能不是一个好选择,因为当系统内存不足时,它会自动清空。 - Hai Feng Kao
3
@HaiFengKao 我希望使用纯Swift,不需要第三方库。我可以自己开始构建解决方案,只是需要正确的路径。你还有其他建议吗? - Jackky White
@HaiFengKao 或许可以将这两个功能结合起来?在他下载完图片后,将其存储在 NSCache 中,在图片“dismiss”之前,将其本地化以备将来使用。 - Jackky White
你肯定可以做到。 - Hai Feng Kao
@Rob 感谢提供的信息。确实,iOS 7改变了NSCache的行为。 - Hai Feng Kao
显示剩余5条评论
1个回答

51

NSCache和持久化存储在很大程度上具有不同的目的。 NSCache将项目保存在内存中,用于实现最佳性能。但它会占用内存(RAM),您确实应该确保如果使用NSCache,则要响应内存警告并在这些情况下清除NSCache。当应用程序终止时,NSCache将丢失。

使用持久性存储缓存(通常是高速缓存文件夹)用于不同的目的,可以使您无需通过某些网络请求重新检索资产,但不会在内存中保存资源。这使其成为跨运行应用程序的会话或在可能遇到内存压力,清除了NSCache但不想从网络重新检索资产的情况下的良好缓存机制。

请注意,我提到了高速缓存文件夹以进行持久性存储,而您似乎预设要使用文档文件夹,但需要考虑两个因素:

  1. Apple越来越关注应用程序仅使用文档文件夹存储不能轻松重建的用户数据,并使用高速缓存文件夹存储易于重新检索的数据。请参阅文件系统基础知识获取更多信息。

  2. 从iOS 11开始,您应该仅将用户可见文档存储在文档文件夹中(请参见WWDC 2017秋季视频,iOS存储最佳实践)。即使您曾经使用过不易重建的内部文件,除非意图最终将其公开给用户,否则您将使用应用程序支持目录,而不是文档文件夹。

简而言之,通常可以使用Caches文件夹作为基于持久存储的缓存。

需要注意的是,我们通常会采用两层缓存机制。将资源同时缓存到NSCacheCaches文件夹中。当要检索资源时,首先检查NSCache(非常快速),如果没有,则检查持久存储,如果还没有,则从网络重新获取该资产。

话虽如此,为了让它更加复杂,还有第三种缓存类型,由NSURLCache提供(即响应网络请求的缓存由NSURLSessionNSURLConnection透明地缓存)。该缓存受到文档不全的规则的影响(例如,它不会缓存任何单个项的大小超过总缓存大小的5%),并且受到网络响应提供的HTTP标头的影响。然而,这种缓存对您来说操作基本透明,并提供内存和持久存储缓存。通常情况下,您可以在不进行任何干预的情况下享受NSURLCache的缓存行为。它是无缝的(当它起作用时)。


谢谢您再次提供的绝妙答案,为了让事情更加简单明了 - 您不建议使用文档目录,而是建议使用机制 NSCache 和 hos 文件夹,按照以下顺序:情况1:在 NSCache 中检查,情况2:在 Cache 目录中检查,情况3:重新下载。后续问题:1)Cache 目录有限制吗? 2)当我在线下载时,我应该立即将其存储在情况1和情况2中吗?还是我等待NSCache将其移除,然后再将其添加到缓存文件夹中?3)我将图像作为文件保存在缓存文件夹中吗?谢谢!!!!!! - Jackky White
缓存文件夹中的限制是总可用持久存储空间(尽管如果您的应用程序可能需要大量存储空间,您可能希望成为一个好公民并对其进行约束)。个人而言,我总是将缓存到持久存储,并在下载时立即重新缓存到NSCache,如果您正在进行惰性加载,则是;如果进行急切加载,则可能不是。是的,在保存到持久存储时,我可能会将其写成文件,尽管NSURLCache使用SQLite。 - Rob
1
最终,我设法想出了一个“还行”的高效解决方案,请告诉我你的想法::::DataTask获取未来单元格的ID -> 检查ID是否存在于个人数据库中(尚未确定使用NSDirectory还是Core Data)-> 如果存在->本地加载图像、文本等->如果不存在->下载它->本地保存->本地加载.......不使用NSCache,只使用CacheDirectory,这会降低首选项吗? - Jackky White
3
@SharadChauhan - 是的,我是。就你的情况而言,要么应用程序只是被暂停了而没有真正终止,要么它正在NSURLCache中查找内容。 - Rob
1
@Rob 你写道:“如果你使用NSCache,你需要响应内存警告并在这些情况下清除NSCache。”但是这不是系统自动完成的吗?这才是NSCache的实际目的。 - Manuel
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接