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

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

  • 沙盒缓存的问题
  • 程序缓存的问题
  • 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 = 3;
 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
 81 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 82
 83     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"app"];
 84
 85     ChaosApp *app = self.apps[indexPath.row];
 86
 87     cell.textLabel.text = app.name;
 88     cell.detailTextLabel.text = app.download;
 89
 90     UIImage *image = self.imageCache[app.icon];
 91
 92     if (image) { // 缓存中有图片
 93
 94         cell.imageView.image = image;
 95
 96     } else { // 缓存中没有,系统沙盒中找图片
 97
 98         // 获取Library\Cache文件
 99         NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
100         // 获取要获取图片的名称
101         NSString *fileName = [app.icon lastPathComponent];
102         // 拼接图片文件路径
103         NSString *fullPath = [cachePath stringByAppendingPathComponent:fileName];
104
105         // 通过图片全路径得到NSData
106         NSData *data = nil;// [NSData dataWithContentsOfFile:fullPath];
107
108         if (data) { // 沙盒中有图片
109
110             cell.imageView.image = [UIImage imageWithData:data];
111
112         } else { // 沙盒Cache文件中也没有
113             // 设置站位图片 -- 作用:系统的imageView默认没有尺寸,如果第一张图片还没显示出来,用户拖拽之后再回来,图片下载完成也不会显示了。其实imageview已经有图片了,只不过imageView没有尺寸看不见。
114             cell.imageView.image = [UIImage imageNamed:@"placeholder"];
115
116             NSOperation *operation = self.opeartions[app.icon]; // 从操作集合中取出对应图片的operation
117             if (operation == nil) {
118                 operation = [NSBlockOperation blockOperationWithBlock:^{
119
120                     // 下载图片
121                     NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:app.icon]];
122
123                     if (data == nil) {
124                         [self.opeartions removeObjectForKey:app.icon];
125                         return;
126                     }
127
128                     UIImage *image = [UIImage imageWithData:data];
129 //                    [NSThread sleepForTimeInterval:1.0]; // 线程睡一秒之后,cell图片出现了混乱
130                     // 将下载的图片存入到缓存集合中,app.icon作为键  image作为值
131                     self.imageCache[app.icon] = image;
132
133                     [[NSOperationQueue mainQueue] addOperationWithBlock:^{
134                         // 回到主线程显示图片
135                         [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
136                     }];
137
138                     // 将图片写入沙盒Cache文件中
139                     [data writeToFile:fullPath atomically:YES];
140
141                     [self.opeartions removeObjectForKey:app.icon];
142                 }];
143             }
144
145             [self.queue addOperation:operation];
146             self.opeartions[app.icon] = operation;
147         }
148     }
149     return cell;
150 }
151
152
153 @end

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

时间: 2024-10-01 21:20:45

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

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

一.NSOperation NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation对象中 然后将NSOperation对象添加到NSOperationQueue中 系统会自动将NSOperationQueue中的NSOperation取出来 将取出的NSOperation封装的操作放到一条新线程中执行 NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类 使用NSOperation子类的方式有3种 N

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

一.iOS中的多线程 多线程的原理(之前多线程这块没好好学,之前对多线程的理解也是错误的,这里更正,好好学习这块) iOS中多线程的实现方案有以下几种 二.NSThread线程类的简单实用(直接上代码) 三.多线程的安全隐患 资源共享 1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源 比如多个线程访问同一个对象.同一个变量.同一个文件 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题(存钱取钱的例子,多个售票员卖票的例子) 安全隐患解决的方法 --- 互斥锁(图解)

【iOS开发】关于图片加载的第三方框架SDWebImage的使用

SDWebImage是一个第三方框架,用于加载网络图片,还有其他一些好的功能 使用步骤 下载地址 https://github.com/rs/SDWebImage 下载以后解压,解压以后是下图 然后将文件中的SDWebImage文件夹拖到项目中,然后在项目中使用 使用框架 #import "SDWebImage/UIImageView+WebCache.h"//引入头文件 -(UITableViewCell *)tableView:(UITableView *)tableView ce

iOS平台软件开发工具(一)-新建的工程使用CocoaPods工具集成第三方框架

CocoaPods是一款集合了上千个第三方开源库的开发工具,能够大幅度的提升团队项目的开发效率,降低时间成本. 那么就看一下CocoaPods这个工具在项目中的使用体现吧. 我们马上用ASIHTTPRequest第三方开源框架,说明如何在我们的项目中使用CocoaPods工具快速集成第三方开源框架. 首先,创建一个iOS平台下的空应用程序工程EmptySample. 然后,在终端中进入新建的工程目录,如图所示 结果如图所示. 在新建的工程根目录下,使用vi命令新建Podfile文件.(注意,不用

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

一.CALayer UIView之所以能显示在屏幕上,完全是因为他内部的一个图层 在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层 当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘制,并且会将所有内容绘制在自己的图层上,绘图完毕后,系统会将图层拷贝到屏幕上,于是就完成了UIView的显示 UIView本身不具备显示的功能,是他内部的层才有显示功能 二.CALayer的基本使用 三.关于CALa

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

一.用户在使用APP的过程中,会产生各种各样的事件.iOS中的事件可以分为3大类型: 二.响应者对象 在iOS中只有继承了了UIResponder的对象才能接受并处理事件,这样的对象称之为“响应者对象” UIApplication.UIViewController.UIView都继承自UIResponder,因此他们都是响应者对象,都能够接受并处理事件 UIResponder内部提供了以下方法来处理事件 三.练习中对UIView的触摸事件进行了熟悉 四.UITouch 一根手指对应一个UITou

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

iOS应用数据存储的常用方式: XML属性列表(plist)归档 Preference(偏好设置) NSKeyedArchiver归档(NSCoding) SQLite3--这里暂且不讲 Core Data--这里暂且不讲 一.应用沙盒 每个iOS应用都有自己的应用沙盒(应用沙盒就是文件系统目录),与其他文件系统隔离.应用必须待在自己的沙盒里,其他应用不能访问该沙盒 应用沙盒的文件系统目录,如下图所示 二.应用沙盒结构分析 应用程序包:(上图中的Layer)包含了所有的资源文件和可执行文件 Do

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

图片拉伸方法一: IOS 5.0以后才有的方法: 1 - (void)viewDidLoad { 2 [super viewDidLoad]; 3 UIImageView *imageView = [[UIImageView alloc] init]; 4 imageView.frame = CGRectMake(30, 30, 300, 300); 5 UIImage *image = [UIImage imageNamed:@"chat_send_press_pic"]; 6 //

iOS边练边学--(Quartz2D)图片裁剪,带圆环的裁剪

一.图片裁剪,示意图 二.带圆环的图片裁剪示意图