查看: 227|回复: 0

[IOS开发教程] iOS多线程实现多图下载功能

发表于 7 天前

本文实例为大家分享了iOS多线程实现多图下载功能的具体代码,供大家参考,具体内容如下

一.模型文件代码如下

  1. // XMGAPP.h
  2. #import <Foundation/Foundation.h>
  3. @interface XMGAPP : NSObject
  4. /** APP的名称 */
  5. @property (nonatomic, strong) NSString *name;
  6. /** APP的图片的url地址 */
  7. @property (nonatomic, strong) NSString *icon;
  8. /** APP的下载量 */
  9. @property (nonatomic, strong) NSString *download;
  10. +(instancetype)appWithDict:(NSDictionary *)dict;
  11. @end
复制代码
  1. // XMGAPP.m
  2. #import "XMGAPP.h"
  3. @implementation XMGAPP
  4. +(instancetype)appWithDict:(NSDictionary *)dict
  5. {
  6. XMGAPP *appM = [[XMGAPP alloc]init];
  7. //KVC
  8. [appM setValuesForKeysWithDictionary:dict];
  9. return appM;
  10. }
  11. @end
复制代码

控制器.m代码如下:

  1. // ViewController.m
  2. #import "ViewController.h"
  3. #import "XMGAPP.h"
  4. @interface ViewController ()
  5. /** tableView的数据源 */
  6. @property (nonatomic, strong) NSArray *apps;
  7. /** 内存缓存 */
  8. @property (nonatomic, strong) NSMutableDictionary *images;
  9. /** 队列 */
  10. @property (nonatomic, strong) NSOperationQueue *queue;
  11. /** 操作缓存 */
  12. @property (nonatomic, strong) NSMutableDictionary *operations;
  13. @end
  14. @implementation ViewController
  15. #pragma mark ----------------------
  16. #pragma mark lazy loading
  17. -(NSOperationQueue *)queue
  18. {
  19. if (_queue == nil) {
  20. _queue = [[NSOperationQueue alloc]init];
  21. //设置最大并发数
  22. _queue.maxConcurrentOperationCount = 5;
  23. }
  24. return _queue;
  25. }
  26. -(NSMutableDictionary *)images
  27. {
  28. if (_images == nil) {
  29. _images = [NSMutableDictionary dictionary];
  30. }
  31. return _images;
  32. }
  33. -(NSArray *)apps
  34. {
  35. if (_apps == nil) {
  36. //字典数组
  37. NSArray *arrayM = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil]];
  38. //字典数组---->模型数组
  39. NSMutableArray *arrM = [NSMutableArray array];
  40. for (NSDictionary *dict in arrayM) {
  41. [arrM addObject:[XMGAPP appWithDict:dict]];
  42. }
  43. _apps = arrM;
  44. }
  45. return _apps;
  46. }
  47. -(NSMutableDictionary *)operations
  48. {
  49. if (_operations == nil) {
  50. _operations = [NSMutableDictionary dictionary];
  51. }
  52. return _operations;
  53. }
  54. #pragma mark ----------------------
  55. #pragma mark UITableViewDatasource
  56. -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
  57. {
  58. return 1;
  59. }
  60. -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  61. {
  62. return self.apps.count;
  63. }
  64. -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  65. {
  66. static NSString *ID = @"app";
  67. //1.创建cell
  68. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
  69. //2.设置cell的数据
  70. //2.1 拿到该行cell对应的数据
  71. XMGAPP *appM = self.apps[indexPath.row];
  72. //2.2 设置标题
  73. cell.textLabel.text = appM.name;
  74. //2.3 设置子标题
  75. cell.detailTextLabel.text = appM.download;
  76. //2.4 设置图标
  77. //先去查看内存缓存中该图片时候已经存在,如果存在那么久直接拿来用,否则去检查磁盘缓存
  78. //如果有磁盘缓存,那么保存一份到内存,设置图片,否则就直接下载
  79. //1)没有下载过
  80. //2)重新打开程序
  81. UIImage *image = [self.images objectForKey:appM.icon];
  82. if (image) {
  83. cell.imageView.image = image;
  84. NSLog(@"%zd处的图片使用了内存缓存中的图片",indexPath.row) ;
  85. }else
  86. {
  87. //保存图片到沙盒缓存
  88. NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
  89. //获得图片的名称,不能包含/
  90. NSString *fileName = [appM.icon lastPathComponent];
  91. //拼接图片的全路径
  92. NSString *fullPath = [caches stringByAppendingPathComponent:fileName];
  93. //检查磁盘缓存
  94. NSData *imageData = [NSData dataWithContentsOfFile:fullPath];
  95. //废除
  96. imageData = nil;
  97. if (imageData) {
  98. UIImage *image = [UIImage imageWithData:imageData];
  99. cell.imageView.image = image;
  100. NSLog(@"%zd处的图片使用了磁盘缓存中的图片",indexPath.row) ;
  101. //把图片保存到内存缓存
  102. [self.images setObject:image forKey:appM.icon];
  103. // NSLog(@"%@",fullPath);
  104. }else
  105. {
  106. //检查该图片时候正在下载,如果是那么久什么都捕捉,否则再添加下载任务
  107. NSBlockOperation *download = [self.operations objectForKey:appM.icon];
  108. if (download) {
  109. }else
  110. {
  111. //先清空cell原来的图片
  112. cell.imageView.image = [UIImage imageNamed:@"Snip20160221_306"];
  113. download = [NSBlockOperation blockOperationWithBlock:^{
  114. NSURL *url = [NSURL URLWithString:appM.icon];
  115. NSData *imageData = [NSData dataWithContentsOfURL:url];
  116. UIImage *image = [UIImage imageWithData:imageData];
  117. NSLog(@"%zd--下载---",indexPath.row);
  118. //容错处理
  119. if (image == nil) {
  120. [self.operations removeObjectForKey:appM.icon];
  121. return ;
  122. }
  123. //演示网速慢的情况
  124. //[NSThread sleepForTimeInterval:3.0];
  125. //把图片保存到内存缓存
  126. [self.images setObject:image forKey:appM.icon];
  127. //NSLog(@"Download---%@",[NSThread currentThread]);
  128. //线程间通信
  129. [[NSOperationQueue mainQueue] addOperationWithBlock:^{
  130. //cell.imageView.image = image;
  131. //刷新一行
  132. [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
  133. //NSLog(@"UI---%@",[NSThread currentThread]);
  134. }];
  135. //写数据到沙盒
  136. [imageData writeToFile:fullPath atomically:YES];
  137. //移除图片的下载操作
  138. [self.operations removeObjectForKey:appM.icon];
  139. }];
  140. //添加操作到操作缓存中
  141. [self.operations setObject:download forKey:appM.icon];
  142. //添加操作到队列中
  143. [self.queue addOperation:download];
  144. }
  145. }
  146. }
  147. //3.返回cell
  148. return cell;
  149. }
  150. -(void)didReceiveMemoryWarning
  151. {
  152. [self.images removeAllObjects];
  153. //取消队列中所有的操作
  154. [self.queue cancelAllOperations];
  155. }
  156. //1.UI很不流畅 --- > 开子线程下载图片
  157. //2.图片重复下载 ---> 先把之前已经下载的图片保存起来(字典)
  158. //内存缓存--->磁盘缓存
  159. //3.图片不会刷新--->刷新某行
  160. //4.图片重复下载(图片下载需要时间,当图片还未完全下载之前,又要重新显示该图片)
  161. //5.数据错乱 ---设置占位图片
  162. /*
  163. Documents:会备份,不允许
  164. Libray
  165. Preferences:偏好设置 保存账号
  166. caches:缓存文件
  167. tmp:临时路径(随时会被删除)
  168. */
  169. @end
复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持程序员之家。



回复

使用道具 举报