#import <pthread.h>
// 创建线程
pthread_t myRestrict;
pthread_create(&myRestrict,NULL, run,NULL);
void *run(void *data)
{
for (int i =0; i<10000; i++) {
NSLog(@"touchesBegan----%d-----%@", i, [NSThreadcurrentThread]);
}
returnNULL;
}
- (void)download:(NSString *)url
{
NSLog(@"下载东西---%@---%@", url, [NSThreadcurrentThread]);
}
/**
* 创建线程的方式3
*/
- (void)createThread3
{
// 这2个不会创建线程,在当前线程中执行
// [self performSelector:@selector(download:) withObject:@"http:"];
// [self download:@"http:"];
[selfperformSelectorInBackground:@selector(download:)withObject:@"http:"];
}
/**
* 创建线程的方式2
*/
- (void)createThread2
{
[NSThreaddetachNewThreadSelector:@selector(download:)toTarget:selfwithObject:@"http:"];
}
/**
* 创建线程的方式1
*/
- (void)createThread1
{
// 创建线程
NSThread *thread = [[NSThreadalloc] initWithTarget:selfselector:@selector(download:)object:@"http:"];
thread.name =@"下载线程";
// 启动线程(调用self的download方法)
[thread start];
}
// 睡眠5秒钟
// [NSThread sleepForTimeInterval:5];
// 3秒后的时间
// NSDate *date = [NSDate dateWithTimeIntervalSinceNow:3];
// [NSThread sleepUntilDate:date];
// [NSThread exit];
// ()小括号里面放的是锁对象
@synchronized(self) {// 开始加锁
int count =self.leftTicketCount;
if (count >0) {
[NSThreadsleepForTimeInterval:0.05];
self.leftTicketCount = count -1;
NSLog(@"%@卖了一张票,剩余%d张票", [NSThreadcurrentThread].name,self.leftTicketCount);
} else {
return;// 退出循环
}
} // 解锁
线程间的通信
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[selfperformSelectorInBackground:@selector(download)withObject:nil];
}
/**
* 下载图片
*/
- (void)download
{
NSLog(@"download---%@", [NSThreadcurrentThread]);
// 1.图片地址
NSString *urlStr =@"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg";
NSURL *url = [NSURLURLWithString:urlStr];
// 2.根据地址下载图片的二进制数据(这句代码最耗时)
NSLog(@"---begin");
NSData *data = [NSDatadataWithContentsOfURL:url];
NSLog(@"---end");
// 3.设置图片
UIImage *image = [UIImageimageWithData:data];
// 4.回到主线程,刷新UI界面(为了线程安全)
[selfperformSelectorOnMainThread:@selector(downloadFinished:)withObject:image waitUntilDone:NO];
// [self performSelector:@selector(downloadFinished:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];
// [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];
NSLog(@"-----done----");
}
- (void)downloadFinished:(UIImage *)image
{
self.imageView.image = image;
NSLog(@"downloadFinished---%@", [NSThreadcurrentThread]);
}
GCD的使用 纯C的中枢调度器 为多核的并行运算提出解决方案,自动利用更多CPU的内核,会自动管理线程的声明周期。
任务block:执行什么操作
对列queue:用来存放任务
同步:只在当前线程中执行任务不具备开启线程的能力。
异步:可以在新的线程中执行任务具备开线程的能力。
使用步骤:确定想做的事情,将任务添加到队列中,GCD自动将队列中的任务取出放到对应的线程中执行。(任务的取出遵循队列FIFO先进先出原则)
// dispatch_sync : 同步,不具备开启线程的能力
// dispatch_async : 异步,具备开启线程的能力
// 并发队列:多个任务可以同时执行
// 串行队列:一个任务执行完后,再执行下一个任务
/**
* async -- 并发队列(最常用)
* 会不会创建线程:会,一般同时开多条
* 任务的执行方式:并发执行
*/
- (void)asyncGlobalQueue
{
// 获得全局的并发队列
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
// 将任务 添加全局队列 中去异步 执行
dispatch_async(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片3---%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片4---%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片5---%@", [NSThreadcurrentThread]);
});
}
/**
* async -- 串行队列(有时候用)
* 会不会创建线程:会,一般只开1条线程
* 任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
*/
- (void)asyncSerialQueue
{
// 1.创建一个串行队列
dispatch_queue_t queue =dispatch_queue_create(“队列名称”,NULL);
// 2.将任务添加到串行队列中异步 执行
dispatch_async(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片3---%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片4---%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片5---%@", [NSThreadcurrentThread]);
});
// 3.非ARC,需要释放创建的队列
// dispatch_release(queue);
}
/**
* async -- 主队列(很常用)
*/
- (void)asyncMainQueue
{
// 1.主队列(添加到主队列中的任务,都会自动放到主线程中去执行)
dispatch_queue_t queue =dispatch_get_main_queue();
// 2.添加任务 到主队列中异步 执行
dispatch_async(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片3---%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片4---%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片5---%@", [NSThreadcurrentThread]);
});
}
/**
* sync -- 主队列(不能用---会卡死)
*/
- (void)syncMainQueue
{
NSLog(@"syncMainQueue----begin--");
// 1.主队列(添加到主队列中的任务,都会自动放到主线程中去执行)
dispatch_queue_t queue =dispatch_get_main_queue();
// 2.添加任务 到主队列中异步 执行
dispatch_sync(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"-----下载图片3---%@", [NSThreadcurrentThread]);
});
NSLog(@"syncMainQueue----end--");
}
/**
* sync -- 并发队列
* 会不会创建线程:不会
* 任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
* 并发队列失去了并发的功能
*/
- (void)syncGlobalQueue
{
// 获得全局的并发队列
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
// 将任务 添加到全局并发队列 中同步 执行
dispatch_sync(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"-----下载图片3---%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"-----下载图片4---%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"-----下载图片5---%@", [NSThreadcurrentThread]);
});
}
/**
* sync -- 串行队列
* 会不会创建线程:不会
* 任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
*/
- (void)syncSerialQueue
{
// 创建一个串行队列
dispatch_queue_t queue =dispatch_queue_create("cn.heima.queue",NULL);
// 将任务 添加到串行队列 中同步 执行
dispatch_sync(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"-----下载图片3---%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"-----下载图片4---%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"-----下载图片5---%@", [NSThreadcurrentThread]);
});
}
CGD线程间通信
// 需要设置按钮的image和backgroundImage,建议先把按钮类型改为custom,才能保证设置成功
// 属性名不能以new开头
// 只有在init开头的构造方法中,才允许对self进行赋值
#define HMGlobalQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)
#define HMMainQueue dispatch_get_main_queue()
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
NSLog(@"donwload---%@", [NSThreadcurrentThread]);
// 1.子线程下载图片
NSURL *url = [NSURLURLWithString:@"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg"];
NSData *data = [NSDatadataWithContentsOfURL:url];
UIImage *image = [UIImageimageWithData:data];
// 2.回到主线程设置图片
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"setting---%@ %@", [NSThreadcurrentThread], image);
[self.buttonsetImage:image forState:UIControlStateNormal];
});
});
}
延时操作
- (void)download:(NSString *)url
{
NSLog(@"download------%@---%@", url, [NSThreadcurrentThread]);
}
- (void)delay3
{
// 3秒后回到主线程执行block中的代码
// dispatch_queue_t queue = dispatch_get_main_queue();
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
// NSLog(@"------task------%@", [NSThread currentThread]);
// });
// 3秒后自动开启新线程执行block中的代码
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
NSLog(@"------task------%@", [NSThreadcurrentThread]);
});
}
- (void)delay2
{
// 一旦定制好延迟任务后,不会卡主当前线程
[selfperformSelector:@selector(download:)withObject:@"http://555.jpg"afterDelay:3];
}
- (void)delay1
{
// 延迟执行不要用sleep,坏处:卡住当前线程
[NSThreadsleepForTimeInterval:3];
NSLog(@"-----下载图片-----");
}
执行一次操作
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"----once");
HMImageDownloader *downloader = [[HMImageDownloader alloc] init];
[downloader download];
});
下载合并多张图片
// 2D绘图 Quartz2D
// 合并图片 --水印
// 1.分别下载2张图片:大图片、LOGO
// 2.合并2张图片
// 3.显示到一个imageView身上
@property (weak,nonatomic) IBOutletUIImageView *imageView;
@property (nonatomic,strong) UIImage *image1;
@property (nonatomic,strong) UIImage *image2;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 1.队列组
dispatch_group_t group =dispatch_group_create();
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
// 2.下载图片1
__blockUIImage *image1 = nil;
dispatch_group_async(group, queue, ^{
NSURL *url1 = [NSURLURLWithString:@"http://g.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee460de6182ff5e0fe99257e80.jpg"];
NSData *data1 = [NSDatadataWithContentsOfURL:url1];
image1 = [UIImageimageWithData:data1];
});
// 3.下载图片2
__blockUIImage *image2 = nil;
dispatch_group_async(group, queue, ^{
NSURL *url2 = [NSURLURLWithString:@"http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png"];
NSData *data2 = [NSDatadataWithContentsOfURL:url2];
image2 = [UIImageimageWithData:data2];
});
// 4.合并图片 (保证执行完组里面的所有任务之后,再执行notify函数里面的block)
dispatch_group_notify(group, queue, ^{
// 开启一个位图上下文
UIGraphicsBeginImageContextWithOptions(image1.size,NO, 0.0);
// 绘制第1张图片
CGFloat image1W = image1.size.width;
CGFloat image1H = image1.size.height;
[image1 drawInRect:CGRectMake(0,0, image1W, image1H)];
// 绘制第2张图片
CGFloat image2W = image2.size.width *0.5;
CGFloat image2H = image2.size.height *0.5;
CGFloat image2Y = image1H - image2H;
[image2 drawInRect:CGRectMake(0, image2Y, image2W, image2H)];
// 得到上下文中的图片
UIImage *fullImage =UIGraphicsGetImageFromCurrentImageContext();
// 结束上下文
UIGraphicsEndImageContext();
// 5.回到主线程显示图片
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = fullImage;
});
});
}
- (void)test2
{
// 异步下载
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
// 1.下载第1张
NSURL *url1 = [NSURLURLWithString:@"http://g.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee460de6182ff5e0fe99257e80.jpg"];
NSData *data1 = [NSDatadataWithContentsOfURL:url1];
self.image1 = [UIImageimageWithData:data1];
[selfbindImages];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
// 2.下载第2张
NSURL *url2 = [NSURLURLWithString:@"http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png"];
NSData *data2 = [NSDatadataWithContentsOfURL:url2];
self.image2 = [UIImageimageWithData:data2];
[selfbindImages];
});
}
- (void)bindImages
{
if (self.image1 ==nil || self.image2 ==nil) return;
// 3.合并图片
// 开启一个位图上下文
UIGraphicsBeginImageContextWithOptions(self.image1.size,NO, 0.0);
// 绘制第1张图片
CGFloat image1W =self.image1.size.width;
CGFloat image1H =self.image1.size.height;
[self.image1drawInRect:CGRectMake(0,0, image1W, image1H)];
// 绘制第2张图片
CGFloat image2W =self.image2.size.width *0.5;
CGFloat image2H =self.image2.size.height *0.5;
CGFloat image2Y = image1H - image2H;
[self.image2drawInRect:CGRectMake(0, image2Y, image2W, image2H)];
// 得到上下文中的图片
UIImage *fullImage =UIGraphicsGetImageFromCurrentImageContext();
// 结束上下文
UIGraphicsEndImageContext();
// 4.回到主线程显示图片
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = fullImage;
});
}
//比较耗时
- (void)test1
{
// 异步下载
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
// 1.下载第1张
NSURL *url1 = [NSURLURLWithString:@"http://g.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee460de6182ff5e0fe99257e80.jpg"];
NSData *data1 = [NSDatadataWithContentsOfURL:url1];
UIImage *image1 = [UIImageimageWithData:data1];
// 2.下载第2张
NSURL *url2 = [NSURLURLWithString:@"http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png"];
NSData *data2 = [NSDatadataWithContentsOfURL:url2];
UIImage *image2 = [UIImageimageWithData:data2];
// 3.合并图片
// 开启一个位图上下文
UIGraphicsBeginImageContextWithOptions(image1.size,NO, 0.0);
// 绘制第1张图片
CGFloat image1W = image1.size.width;
CGFloat image1H = image1.size.height;
[image1 drawInRect:CGRectMake(0,0, image1W, image1H)];
// 绘制第2张图片
CGFloat image2W = image2.size.width *0.5;
CGFloat image2H = image2.size.height *0.5;
CGFloat image2Y = image1H - image2H;
[image2 drawInRect:CGRectMake(0, image2Y, image2W, image2H)];
// 得到上下文中的图片
UIImage *fullImage =UIGraphicsGetImageFromCurrentImageContext();
// 结束上下文
UIGraphicsEndImageContext();
// 4.回到主线程显示图片
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = fullImage;
});
});
}
NSOperation (OC基于GCD)
NSOperation是个抽象类并不具备封装操作的能力,必须使用它的子类 (NSInvocationOperation、NSBlockOperation、自定义子类继承NSOperation)
NSOperation之间可以升值依赖来保证执行顺序,可在不同的queue的NSOperation之间创建依赖关系
NSOperation操作完成的监听
对列可以取消、暂停、恢复
// [queue cancelAllOperations]; 取消队列中的所有任务(不可恢复)
// [queue setSuspended:YES]; 暂停队列中的所有任务
// [queue setSuspended:NO]; 恢复队列中的所有任务
NSInvocationOperation的使用(不常用)
NSOperationQueue *queue = [[NSOperationQueuealloc] init];
NSInvocationOperation *operation = [[NSInvocationOperationalloc] initWithTarget:selfselector:@selector(download)object:nil];
// operation直接调用start,是同步执行(在当前线程执行操作!)
// [operation start];
// 如果添加操作到队列中,会自动异步执行
[queue addOperation:operation];
- (void)download
{
NSLog(@"download-----%@", [NSThreadcurrentThread]);
}
NSBlockOperation的使用只有一个任务的时在主线程中执行 多于一个会新开线程异步执行
-(void)test2{
NSBlockOperation *operation1 = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"---下载图片----11---%@", [NSThreadcurrentThread]);
}];
[operation1 addExecutionBlock:^{
NSLog(@"---下载图片----12---%@", [NSThreadcurrentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"---下载图片----2---%@", [NSThreadcurrentThread]);
}];
NSBlockOperation *operation3 = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"---下载图片----3---%@", [NSThreadcurrentThread]);
}];
NSBlockOperation *operation4 = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"---下载图片----4---%@", [NSThreadcurrentThread]);
}];
//创建队列
NSOperationQueue *queue = [[NSOperationQueuealloc] init];
// 主队列
// NSOperationQueue *queue = [NSOperationQueue mainQueue];
// 2.添加操作到队列中(自动异步执行)
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
[queue addOperation:operation4];
}
- (void)test
{
// NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
// NSLog(@"---下载图片----1---%@", [NSThread currentThread]);
// }];
NSBlockOperation *operation = [[NSBlockOperationalloc] init];
[operation addExecutionBlock:^{
NSLog(@"---下载图片----1---%@", [NSThreadcurrentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"---下载图片----2---%@", [NSThreadcurrentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"---下载图片----3---%@", [NSThreadcurrentThread]);
}];
[operation start];
// 任务数量 > 1,才会开始异步执行
}
NSOperationQueue
// 1.创建一个队列(非主队列)
NSOperationQueue *queue = [[NSOperationQueuealloc] init];
// 2.设置最大并发(最多同时并发执行3个任务)
queue.maxConcurrentOperationCount =3;
// 3.添加操作到队列中(自动异步执行任务,并发)
NSBlockOperation *operation1 = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"下载图片1---%@", [NSThreadcurrentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"下载图片2---%@", [NSThreadcurrentThread]);
}];
NSBlockOperation *operation3 = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"下载图片3---%@", [NSThreadcurrentThread]);
}];
NSBlockOperation *operation4 = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"下载图片4---%@", [NSThreadcurrentThread]);
}];
NSInvocationOperation *operation5 = [[NSInvocationOperationalloc] initWithTarget:selfselector:@selector(download)object:nil];
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
[queue addOperation:operation4];
[queue addOperation:operation5];
[queue addOperationWithBlock:^{
NSLog(@"下载图片5---%@", [NSThreadcurrentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"下载图片6---%@", [NSThreadcurrentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"下载图片7---%@", [NSThreadcurrentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"下载图片8---%@", [NSThreadcurrentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"下载图片9---%@", [NSThreadcurrentThread]);
}];
[queue cancelAllOperations];
- (void)download
{
NSLog(@"download---%@", [NSThreadcurrentThread]);
}
任务顺序异步执行
- (void)dependency
{
/**
假设有A、B、C三个操作,要求:
1. 3个操作都异步执行
2. 操作C依赖于操作B
3. 操作B依赖于操作A
*/
// 1.创建一个队列(非主队列)
NSOperationQueue *queue = [[NSOperationQueuealloc] init];
// 2.创建3个操作
NSBlockOperation *operationA = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"A1---%@", [NSThreadcurrentThread]);
}];
// 添加任务
// [operationA addExecutionBlock:^{
// NSLog(@"A2---%@", [NSThread currentThread]);
// }];
//监听任务完成以后执行操作
// [operationA setCompletionBlock:^{
// NSLog(@"AAAAA---%@", [NSThread currentThread]);
// }];
NSBlockOperation *operationB = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"B---%@", [NSThreadcurrentThread]);
}];
NSBlockOperation *operationC = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"C---%@", [NSThreadcurrentThread]);
}];
// 设置依赖
[operationB addDependency:operationA];
[operationC addDependency:operationB];
// 3.添加操作到队列中(自动异步执行任务)
[queue addOperation:operationC];
[queue addOperation:operationA];
[queue addOperation:operationB];
}
NSOperation通信
NSOperationQueue *queue = [[NSOperationQueuealloc] init];
[queue addOperationWithBlock:^{
// 1.异步下载图片
NSURL *url = [NSURLURLWithString:@"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg"];
NSData *data = [NSDatadataWithContentsOfURL:url];
UIImage *image = [UIImageimageWithData:data];
// 2.回到主线程,显示图片
// [self performSelectorOnMainThread:<#(SEL)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>];
// dispatch_async(dispatch_get_main_queue(), ^{
//
// });
[[NSOperationQueuemainQueue] addOperationWithBlock:^{
self.imageView.image = image;
}];
}];
NSOperation重复下载与缓存 问题
/**
* 存放所有下载操作的队列
*/
@property (nonatomic,strong) NSOperationQueue *queue;
/**
* 存放所有的下载操作(url是key,operation对象是value)
*/
@property (nonatomic,strong) NSMutableDictionary *operations;
/**
* 存放所有下载完的图片
*/
@property (nonatomic,strong) NSMutableDictionary *images;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
staticNSString *ID = @"app";
UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:ID];
if (!cell) {
cell = [[UITableViewCellalloc] initWithStyle:UITableViewCellStyleSubtitlereuseIdentifier:ID];
}
// 取出模型
ModelApp *app = self.apps[indexPath.row];
// 设置基本信息
cell.textLabel.text = app.name;
cell.detailTextLabel.text = app.download;
// 先从images缓存中取出图片url对应的UIImage
UIImage *image =self.images[app.icon];
if (image) {// 说明图片已经下载成功过(成功缓存)
cell.imageView.image = image;
} else {// 说明图片并未下载成功过(并未缓存过)
// 获得caches的路径,拼接文件路径
NSString *file = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask,YES) lastObject] stringByAppendingPathComponent:[app.icon lastPathComponent]]
// 先从沙盒中取出图片
NSData *data = [NSData dataWithContentsOfFile:file];
if (data) {// 沙盒中存在这个文件
cell.imageView.image = [UIImage imageWithData:data];
} else {// 沙盒中不存在这个文件
// 显示占位图片
cell.imageView.image = [UIImageimageNamed:@"placeholder"];
// 下载图片
[self download:app.icon indexPath:indexPath];
}
}
return cell;
}
/**
* 下载图片
*
* @param imageUrl图片的url
*/
- (void)download:(NSString *)imageUrl indexPath:(NSIndexPath *)indexPath
{
// 取出当前图片url对应的下载操作(operation对象)
NSBlockOperation *operation =self.operations[imageUrl];
if (operation)return;
// 创建操作,下载图片
__weaktypeof(self) appsVc =self;
operation = [NSBlockOperationblockOperationWithBlock:^{
NSURL *url = [NSURLURLWithString:imageUrl];
NSData *data = [NSDatadataWithContentsOfURL:url]; // 下载
UIImage *image = [UIImageimageWithData:data]; // NSData -> UIImage
// 回到主线程
[[NSOperationQueuemainQueue] addOperationWithBlock:^{
// 存放图片到字典中
if (image) {
appsVc.images[imageUrl] = image;
#warning 将图片存入沙盒中
// UIImage --> NSData --> File(文件)
NSData *data =UIImagePNGRepresentation(image);
// 获得caches的路径,拼接文件路径
// NSString *file = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[imageUrl lastPathComponent]];
[data writeToFile:HMAppImageFile(imageUrl)atomically:YES];
// UIImageJPEGRepresentation(<#UIImage *image#>, 1.0)
}
// 从字典中移除下载操作 (防止operations越来越大,保证下载失败后,能重新下载)
[appsVc.operationsremoveObjectForKey:imageUrl];
// 刷新表格
[appsVc.tableViewreloadRowsAtIndexPaths:@[indexPath]withRowAnimation:UITableViewRowAnimationNone];
}];
}];
// 添加操作到队列中
[self.queueaddOperation:operation];
// 添加到字典中 (这句代码为了解决重复下载)
self.operations[imageUrl] = operation;
}
/**
* 当用户开始拖拽表格时调用
*/
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
// 暂停下载
[self.queuesetSuspended:YES];
}
/**
* 当用户停止拖拽表格时调用
*/
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
// 恢复下载
[self.queuesetSuspended:NO];
}
- (void)didReceiveMemoryWarning
{
[superdidReceiveMemoryWarning];
// 移除所有的下载操作缓存
[self.queuecancelAllOperations];
[self.operationsremoveAllObjects];
// 移除所有的图片缓存
[self.imagesremoveAllObjects];
}