iOS开发网络多线程之多图下载

一. 多线程中多图片下载

头像通过网络下载得到

效果图如下:

二. 设计思路

    利用tableView实现多行数据的现实,图标通过网络下载很耗时,需要在子线程中执行.

    cell中的ImageView的设置:

1. 首先到图片缓存池中取(定义一个存放图片的的字典属性),如果有直接设置;

2. 如果图片缓存池没有,再到沙盒缓存cache中查看是否存在,如果有直接设置,并把沙盒中的图片写入到图片缓存池中

3. 如果沙盒cache中也没有,就需要开线程下载;

4. 首先判断当前图片是否有任务在下载(定义一个存放任务的字典属性);

5. 如何没有当前没有任务在下载,就开启一个子线程进行数据下载

6. 下载得到一个图片

    6.1 这时需要优化,考虑到图片路径不对或者网络比较差,下载图片失败,得到的图片为空,这时需要判断如果为空就直接return,并把此任务从缓存池中移除

7. 下载的图片写入到图片缓存池中

8. 下载的图片同时写入到沙盒中

9. 在主线程中刷新数据

10. 将操作添加到任务缓存池中

11. 队列中添加操作

  1. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  2. {
  3. static NSString *ID = @"APP";
  4. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
  5. if (!cell) {
  6. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
  7. }
  8. LDApp *app = self.apps[indexPath.row];
  9. cell.textLabel.text = app.name;
  10. cell.detailTextLabel.text = app.download;
  11. /*
  12. 1.先到缓存中查看有没有图片,判断如有直接设置
  13. 2.如果没有进入沙盒中查看是否有icon中的后缀图片,如有直接取出设置,并写入到缓存中
  14. 3.如果没有则下载,则查看队列中是否有此下载任务,如果没有就下载完成之后设置并写入到缓存中
  15. */
  16. // 1.从图片缓存池中取出图片
  17. UIImage *image = self.cacheDict[app.icon];
  18. if (image) {
  19. cell.imageView.image = image;
  20. NSLog(@"从缓存池中加载图片-%zd", indexPath.row);
  21. } else {
  22. // 获取沙盒缓存路径
  23. NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
  24. // 截取app名称字符串
  25. NSString *appName = [app.icon lastPathComponent];
  26. // 拼接路径
  27. NSString *appCachePath = [cachePath stringByAppendingPathComponent:appName];
  28. // 加载沙盒路径图片
  29. NSData *data = [NSData dataWithContentsOfFile:appCachePath];
  30. // 判断沙盒路径图片是否存在
  31. if (data) { // 存在
  32. NSLog(@"从沙盒中加载图片-%zd", indexPath.row);
  33. // 直接设置
  34. cell.imageView.image = [UIImage imageWithData:data];
  35. // 写入缓存中
  36. [self.cacheDict setObject:cell.imageView.image forKey:app.icon];
  37. } else { // 沙盒不存在,进行下载
  38. // 设置一个占位图
  39. cell.imageView.image = [UIImage imageNamed:@"t012fea7312194537c2"];
  40. // 判断任务缓存池中是否存在下载此app图片的任务
  41. NSBlockOperation *operation = self.operationDict[app.icon];
  42. if (operation == nil) { // 任务缓存池中没有此任务才进行下载
  43. // 封装任务
  44. operation = [NSBlockOperation blockOperationWithBlock:^{
  45. NSLog(@"下载图片-%zd", indexPath.row);
  46. // 获取图片URL
  47. NSURL *url = [NSURL URLWithString:app.icon];
  48. // 加载二进制
  49. NSData *data = [NSData dataWithContentsOfURL:url];
  50. // 将二进制转为图片
  51. UIImage *image = [UIImage imageWithData:data];
  52. // 加载的图片路径不正确或者网速慢下载的图片为空即为下载失败,直接return
  53. if (image == nil) {
  54. // 将任务移除,如果不移除下次就不能进入进行下载,因为当前操作在任务缓存池中
  55. [self.operationDict removeObjectForKey:app.icon];
  56. return;
  57. }
  58. // 将图片加入到图片缓存池中
  59. self.cacheDict[app.icon] = image;
  60. // 将图片写入到沙盒中
  61. [data writeToFile:appCachePath atomically:YES];
  62. // 刷新UI
  63. [[NSOperationQueue mainQueue] addOperationWithBlock:^{
  64. //cell.imageView.image = image;
  65. // 局部刷新
  66. [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
  67. // 下载完成之后将任务移除任务池
  68. [self.operationDict removeObjectForKey:app.icon];
  69. }];
  70. }];
  71. // 任务加入到缓存池中
  72. self.operationDict[app.icon] = operation;
  73. [self.queue addOperation:operation];
  74. }
  75. }
  76. }
  77. return cell;
  78. }


三.第三方框架(SDWebImage)

1. 多图下载

第一个参数: 图片的URL路径

第二个参数: 占位图片

  1. // 第三方框架下载多图
  2. [cell.imageView sd_setImageWithURL:[NSURL URLWithString:app.icon] placeholderImage:[UIImage imageNamed:@"t012fea7312194537c2"]];


2. 内存告警清除缓存

清除缓存数据,在applictionDelegate中执行缓存清除

引入"SDWebImageManager.h"头文件

-(void)applicationDidReceiveMemoryWarning:(UIApplication *)application方法中进行对缓存数据清除

获取图片管理单例执行cancelAll法进行缓存清除

cancelAll方法内部已经实现了clearDisk方法

  1. #import "AppDelegate.h"
  2. #import "SDWebImageManager.h"
  3. @interface AppDelegate ()
  4. @end
  5. @implementation AppDelegate
  6. -(void)applicationDidReceiveMemoryWarning:(UIApplication *)application
  7. {
  8. //当发生内存警告的时候如何处理
  9. //1.取消当前正在下载的所有操作
  10. [[SDWebImageManager sharedManager] cancelAll];
  11. //2.图片缓存处理
  12. /*
  13. kDefaultCacheMaxCacheAge:默认缓存周期是一周
  14. maxCacheSize:
  15. cleanDisk:找到缓存文件,先删除过期缓存,统计当前缓存文件的大小(currentSzie),如果发现大于最大缓存数量(currentSzie>maxCacheSize),那么会继续删除,按照缓存文件产生的事件顺序,从远到进删除,直到小于为止
  16. clearDisk:直接删除,然后创建新的文件夹
  17. */
  18. //内部已经实现了
  19. // [[SDWebImageManager sharedManager].imageCache clearDisk];
  20. }
  21. @end


原文地址:https://www.cnblogs.com/Xfsrn/p/5000313.html