一、自己实现多图片下载应该注意的问题

  • 沙盒缓存的问题
  • 程序缓存的问题
  • cell重复利用显示图片混乱的问题 -- 用户拖拽快,下载图片慢导致的
  • 解决图片混乱引入NSOperation集合的问题
  • 资源下载失败的问题(练习中没有出现过,但是一定要考虑)
  1. #import "ChaosViewController.h"
  2. #import "ChaosApp.h"
  3.  
  4. @interface ChaosViewController ()
  5. /** 模型集合 */
  6. @property(nonatomic,strong) NSMutableArray *apps;
  7. /** 图片缓存 */
  8. @property(nonatomic,strong) NSMutableDictionary *imageCache;
  9.  
  10. /** queue */
  11. @property(nonatomic,strong) NSOperationQueue *queue;
  12.  
  13. /** 所有的操作对象 */
  14. @property(nonatomic,strong) NSMutableDictionary *opeartions;
  15.  
  16. @end
  17.  
  18. @implementation ChaosViewController
  19.  
  20. - (NSMutableDictionary *)opeartions
  21. {
  22. if (_opeartions == nil) {
  23.  
  24. _opeartions = [NSMutableDictionary dictionary];
  25.  
  26. }
  27. return _opeartions;
  28. }
  29.  
  30. - (NSOperationQueue *)queue
  31. {
  32. if (_queue == nil) {
  33.  
  34. // 设置最大线程数
  35. _queue.maxConcurrentOperationCount = ;
  36.  
  37. _queue = [[NSOperationQueue alloc] init];
  38. }
  39. return _queue;
  40. }
  41.  
  42. - (NSMutableDictionary *)imageCache
  43. {
  44. if (_imageCache == nil) {
  45.  
  46. _imageCache = [NSMutableDictionary dictionary];
  47. }
  48. return _imageCache;
  49. }
  50.  
  51. - (NSMutableArray *)apps
  52. {
  53. if (_apps == nil) {
  54.  
  55. _apps = [NSMutableArray array];
  56.  
  57. NSString *path = [[NSBundle mainBundle] pathForResource:@"apps.plist" ofType:nil];
  58. NSArray *arrDict = [NSArray arrayWithContentsOfFile:path];
  59.  
  60. for (NSDictionary *dict in arrDict) {
  61. ChaosApp *app = [ChaosApp appWithDict:dict];
  62. [_apps addObject:app];
  63. }
  64. }
  65.  
  66. return _apps;
  67. }
  68.  
  69. - (void)viewDidLoad {
  70. [super viewDidLoad];
  71. }
  72.  
  73. #pragma mark - Table view data source
  74.  
  75. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  76.  
  77. return self.apps.count;
  78. }
  79.  
  80. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  81.  
  82. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"app"];
  83.  
  84. ChaosApp *app = self.apps[indexPath.row];
  85.  
  86. cell.textLabel.text = app.name;
  87. cell.detailTextLabel.text = app.download;
  88.  
  89. UIImage *image = self.imageCache[app.icon];
  90.  
  91. if (image) { // 缓存中有图片
  92.  
  93. cell.imageView.image = image;
  94.  
  95. } else { // 缓存中没有,系统沙盒中找图片
  96.  
  97. // 获取Library\Cache文件
  98. NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
  99. // 获取要获取图片的名称
  100. NSString *fileName = [app.icon lastPathComponent];
  101. // 拼接图片文件路径
  102. NSString *fullPath = [cachePath stringByAppendingPathComponent:fileName];
  103.  
  104. // 通过图片全路径得到NSData
  105. NSData *data = nil;// [NSData dataWithContentsOfFile:fullPath];
  106.  
  107. if (data) { // 沙盒中有图片
  108.  
  109. cell.imageView.image = [UIImage imageWithData:data];
  110.  
  111. } else { // 沙盒Cache文件中也没有
  112. // 设置站位图片 -- 作用:系统的imageView默认没有尺寸,如果第一张图片还没显示出来,用户拖拽之后再回来,图片下载完成也不会显示了。其实imageview已经有图片了,只不过imageView没有尺寸看不见。
  113. cell.imageView.image = [UIImage imageNamed:@"placeholder"];
  114.  
  115. NSOperation *operation = self.opeartions[app.icon]; // 从操作集合中取出对应图片的operation
  116. if (operation == nil) {
  117. operation = [NSBlockOperation blockOperationWithBlock:^{
  118.  
  119. // 下载图片
  120. NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:app.icon]];
  121.  
  122. if (data == nil) {
  123. [self.opeartions removeObjectForKey:app.icon];
  124. return;
  125. }
  126.  
  127. UIImage *image = [UIImage imageWithData:data];
  128. // [NSThread sleepForTimeInterval:1.0]; // 线程睡一秒之后,cell图片出现了混乱
  129. // 将下载的图片存入到缓存集合中,app.icon作为键 image作为值
  130. self.imageCache[app.icon] = image;
  131.  
  132. [[NSOperationQueue mainQueue] addOperationWithBlock:^{
  133. // 回到主线程显示图片
  134. [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
  135. }];
  136.  
  137. // 将图片写入沙盒Cache文件中
  138. [data writeToFile:fullPath atomically:YES];
  139.  
  140. [self.opeartions removeObjectForKey:app.icon];
  141. }];
  142. }
  143.  
  144. [self.queue addOperation:operation];
  145. self.opeartions[app.icon] = operation;
  146. }
  147. }
  148. return cell;
  149. }
  150.  
  151. @end

二、使用SDWebImage框架之后,上面所有的担心都不用考虑。

iOS边练边学--多线程练习的多图片下载 以及 使用第三方框架(SDWebImage)的多图片下载的更多相关文章

  1. iOS边练边学--多线程介绍、NSThread的简单实用、线程安全以及线程之间的通信

    一.iOS中的多线程 多线程的原理(之前多线程这块没好好学,之前对多线程的理解也是错误的,这里更正,好好学习这块) iOS中多线程的实现方案有以下几种 二.NSThread线程类的简单实用(直接上代码 ...

  2. iOS边练边学--多线程NSOperation介绍,子类实现多线程的介绍(任务和队列),队列的取消、暂停(挂起)和恢复,操作依赖与线程间的通信

    一.NSOperation NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation对象中 然后将NSOperation对象添加 ...

  3. iOS边练边学--Http网络再学习,简单介绍

    一.URL 什么是URL URL中常见的协议 二.Http Http的基本通信过程 发送Http请求的方法 GET 和 POST 对比 GET 和 POST 的选择 三.iOS中的Http学习 iOS ...

  4. iOS边练边学--CALayer,非根层隐式动画,钟表练习

    一.CALayer UIView之所以能显示在屏幕上,完全是因为他内部的一个图层 在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性 ...

  5. iOS边练边学--UIGestureRecognizer手势识别器简单介绍

    iOS 3.2之后,苹果退出了手势识别功能(Gesture Recognizer),在触摸事件处理方面,大大简化了开发者的开发难度. 一.UIGestureRecognizer UIGestureRe ...

  6. iOS边练边学--触摸事件以及能够拖拽的UIView的练习

    一.用户在使用APP的过程中,会产生各种各样的事件.iOS中的事件可以分为3大类型: 二.响应者对象 在iOS中只有继承了了UIResponder的对象才能接受并处理事件,这样的对象称之为“响应者对象 ...

  7. iOS边练边学--应用数据存储的常用方式(plist,Preference,NSKeyedArchiver)其中的三种

    iOS应用数据存储的常用方式: XML属性列表(plist)归档 Preference(偏好设置) NSKeyedArchiver归档(NSCoding) SQLite3--这里暂且不讲 Core D ...

  8. iOS边练边学--图片的拉伸

    图片拉伸方法一: IOS 5.0以后才有的方法: - (void)viewDidLoad { [super viewDidLoad]; UIImageView *imageView = [[UIIma ...

  9. iOS边练边学--NSURLSessionDataTask实现文件真正的断点续传

    实现重点: NSURLSessionDataTask要设置请求头,从路径中获取文件已经下载的长度(文件没有下载过的话,长度为0).通过这个长度设置请求的Range 如图: 接收到请求的时候key:文件 ...

随机推荐

  1. fiddler对手机进行抓包

    1.安装fiddler web debugger 2.Tools -->telerik fiddler options-->connections,勾选allow remote compu ...

  2. ZBrush中如何才能快速完成脸部雕刻(上)

    骨骼,是一门基础艺术,几百年来一直为伟大的艺术大师所研究,它曾经,也将一直是创作现实且可信角色的关键,提高骨骼知识更将大大提高雕刻技能. 查看更多内容请直接前往:http://www.zbrushcn ...

  3. ZBrush中的Clip剪切笔刷怎么快速运用

    Clip剪切笔刷可以对模型网格进行剪切操作,也可以叫做剪切笔刷.接下来看一下Clip切割笔刷在ZBrush中是如何使用的. 查看更多内容请直接前往:http://www.zbrushcn.com/ji ...

  4. codeforces 710E E. Generate a String(dp)

    题目链接: E. Generate a String time limit per test 2 seconds memory limit per test 512 megabytes input s ...

  5. Topcoder SRM 618 Div2 --900

    题意:给定两个NxN的棋盘,每个棋盘都有一个‘车’的摆放状态,问进行若干次交换,能否使棋盘1变为棋盘2. 交换规则:每次选两个‘车’,坐标分别为(r1,c1),(r2,c2),如果r1<r2并且 ...

  6. 使用Android Studio搭建Android集成开发环境(图文教程)

    ​[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...

  7. AC日记——搞笑世界杯 codevs 1060(dp)

    题目描述 Description 随着世界杯小组赛的结束,法国,阿根廷等世界强队都纷纷被淘汰,让人心痛不已. 于是有 人组织了一场搞笑世界杯,将这些被淘汰的强队重新组织起来和世界杯一同比赛.你和你的朋 ...

  8. Selenium Webdriver元素定位的八种常用方式

    楼主原创,欢迎学习和交流,码字不容易,转载请注明出处,谢谢. 在使用selenium webdriver进行元素定位时,通常使用findElement或findElements方法结合By类返回的元素 ...

  9. 【ArcGIS二次开发】CreateFeature报错(HRESULT E_FAIL)

    在VS2010下基于ArcGIS 10.1做二次开发时遇到个奇怪的问题,对于MXD工程文档中已经存在的图层,获取其FeatureClass可以调用CreateFeature()函数生成要素,但是对于通 ...

  10. Elasticsearch 相关名词理解

    Cluster包含多个node,Indices不应该理解成动词索引,Indices可理解成关系数据库中的databases,Indices可包含多个Index,Index对应关系数据库中的databa ...