线程 、GCD、NSOperation用法总结,重复下载,线程之间的通信

#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 =@"下载线程";

    

    // 启动线程(调用selfdownload方法)

    [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线程间通信



// 需要设置按钮的imagebackgroundImage,建议先把按钮类型改为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

{

    /**

     假设有ABC三个操作,要求:

     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;


/**

 *  存放所有的下载操作(urlkeyoperation对象是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];

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值