NSURLSession用于网络图像下载+缓存

有许多第三方库用于加载网络映像,然后将其存储到磁盘和/或内存中。

但是,使用简单的NSURLSession API调用很容易实现它。

这是代码:

NSURLCache *myCache = [[NSURLCache alloc] initWithMemoryCapacity: 16384 diskCapacity: 268435456 diskPath: cachePath]; // these numbers are only for the usage example. defaultConfigObject.URLCache = myCache; defaultConfigObject.requestCachePolicy = NSURLRequestUseProtocolCachePolicy; _session = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate:self delegateQueue: [NSOperationQueue mainQueue]]; _dataTask = [_session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){ if (!error){ UIImage* theImage = [UIImage imageWithData:data]; dispatch_async(dispatch_get_main_queue(), ^{ self.image = theImage; }); } }]; [_dataTask resume]; 

此代码根据http缓存策略下载图像(来自给定的URL)并将其存储到内存+磁盘。

从UIImageView派生MyNetworkImageView并将上述代码添加到setURL:方法也很简单。

我的问题是

使用其他第三方框架有什么好处,例如AFNetworking,FastImageCache,SDWebImage,SDImageCache?

  1. 这些框架中的缓存更具确定性。 NSURLCache使用的NSURLSession是(a)有点不透明(例如,我从未见过记录的5%阈值); (b)由您的服务器提供的响应标头控制。

  2. 在您简单地声明NSURLCache “足够好”之前,我建议严格测试应用程序并确保缓存(esp持久存储缓存:运行应用程序,下载图像;终止(不仅仅是暂停)应用程序;重新运行应用程序)就像你希望的那样工作。 确保测试运行时缓存以及持久存储缓存。

  3. 顺便说一下,你的内存缓存似乎很小(任何超过5%的缓存大小都不会被缓存)。 这是一个意见问题,但我通常希望看到接近16mb而不是16kb的东西。 实际上,这不会缓存任何超过800字节左右的东西!

  4. 这些框架也提供了许多其他优点。

    • AFNetworking和SDWebImage提供的UIImageView类别是实现异步图像检索的最简单方法。 特别是,当在表/集合视图中重用单元格时,它将取消先前的请求,确保对可见单元格的图像请求进行优先级排序。 (您不希望快速滚动到表格中的第100行,并且在开始下载可见单元格的图像之前必须等待下载99个不久的可见图像。)

    • 如果生成复杂的HTTP请求,AFNetworking可让您专注于应用程序逻辑,而不是编写和测试复杂的网络代码。

在iOS中依赖NSURLCache的底线在过去一直存在问题,特别是如果你不控制服务器的话。 这些类也提供其他优点(例如,使用UIImageView类别)。

NSURLCache是​​一个很好的工具,特别是当您需要重新validation机制时,NSURLCache会为您透明地处理HTTP重新validation。 NSURLSession也是Cocoa网络向前迈出的一大步 。

但是,以有效的方式实现图像提取并不容易。 您可能在app中有一些特殊要求:

  1. 避免主线程上的图像解压缩,这是昂贵的,尤其是对于jpg。
  2. 在NSURLCache之上有一个单独的内存缓存层来存储解压缩的图像,并能够在主线程上同步检索它们。 即使您使用NSCache,管理内存缓存也不是那么简单。
  3. 在网络层上有一些抽象,以便能够在必要时添加对更多图像格式的支持,如gifwebp 。 并以其他方式扩展图像获取。
  4. 将相同的图像请求分组,而不创建过多的会话任务
  5. 能够有效地预热图像
  6. 有办法首先获取低分辨率占位符,然后等待高分辨率图像

和更多。

AFNetworking,FastImageCache,SDWebImage,SDImageCache

这些框架都没有使用NSURLSession(有些甚至有自己的磁盘缓存实现),请查看Nuke / DFImageManager 。 它建立在NSURLSession的基础之上,它具有上述所有function,并且还有多个子规格,可以将AFNetworking *集成为网络堆栈,将FLAnimatedImage集成为动画GIF引擎等等。

* AFNetworking基于NSRULSession,但它们的图像获取实现仍然基于NSURLConnection(AFHTTPRequestOperation)。