代码示例:
// // ViewController.m // TestNSOperationQueue // // Created by taobaichi on 2017/3/21. // Copyright © 2017年 MaChao. All rights reserved. // #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //创建NSInvocationOperation对象,封装操作 NSInvocationOperation * operation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(testOperation1) object:nil]; NSInvocationOperation * operation2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(testOperation2) object:nil]; //创建对象,封装操作 NSBlockOperation * operation3 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"-----NSBlockOperation--3--1---- %@",[NSThread currentThread]); }]; [operation3 addExecutionBlock:^{ NSLog(@"-----NSBlockOperation--3--2---- %@",[NSThread currentThread]); }]; //创建NSOperationQueue NSOperationQueue * queue = [[NSOperationQueue alloc]init]; //把操作添加到队列中 [queue addOperation:operation1]; [queue addOperation:operation2]; [queue addOperation:operation3]; } -(void)testOperation1 { NSLog(@"-----NSInvocationOperation--1---- %@",[NSThread currentThread]); } -(void)testOperation2 { NSLog(@"-----NSInvocationOperation--2---- %@",[NSThread currentThread]); } @end
打印效果:
2017-03-21 13:36:39.594 TestNSOperationQueue[5185:159392] -----NSInvocationOperation--2---- <NSThread: 0x60800007b480>{number = 4, name = (null)} 2017-03-21 13:36:39.594 TestNSOperationQueue[5185:159391] -----NSInvocationOperation--1---- <NSThread: 0x600000269f40>{number = 3, name = (null)} 2017-03-21 13:36:39.594 TestNSOperationQueue[5185:159394] -----NSBlockOperation--3--1---- <NSThread: 0x60000026a0c0>{number = 5, name = (null)} 2017-03-21 13:36:39.594 TestNSOperationQueue[5185:159414] -----NSBlockOperation--3--2---- <NSThread: 0x608000266240>{number = 6, name = (null)}
注意:系统自动将
NSOperationQueue中
的NSOperation
对象取出,将其封装的操作放到一条新的线程中执行,上面的代码示例一共有四个任务,operation1
和operation2
分别有一个任务,operation3
有2个任务。一共四个任务,开启了四条线程,通过任务执行的时间全部是2017-03-21 13:36:39.594
可以看出,这些任务是并行
执行的
提示:队列的取出是有顺序的,与打印结果并不矛盾。这就好比,选手A,B,C虽然起跑的顺序是先A,后B,然后C,但是到达终点的顺序却不一定是A,B在前,C在后。
下面使用for循环打印,可以更明显的看出任务是并行执行的
代码示例:
// // ViewController.m // TestNSOperationQueue // // Created by taobaichi on 2017/3/21. // Copyright © 2017年 MaChao. All rights reserved. // #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //创建NSInvocationOperation对象,封装操作 NSInvocationOperation * operation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(testOperation1) object:nil]; NSInvocationOperation * operation2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(testOperation2) object:nil]; //创建对象,封装操作 NSBlockOperation * operation3 = [NSBlockOperation blockOperationWithBlock:^{ for (int i = 0; i < 5; i++) { NSLog(@"-----NSBlockOperation----3--1---- %@",[NSThread currentThread]); } }]; [operation3 addExecutionBlock:^{ for (int i = 0; i < 5; i++) { NSLog(@"-----NSBlockOperation----3--2---- %@",[NSThread currentThread]); } }]; //创建NSOperationQueue NSOperationQueue * queue = [[NSOperationQueue alloc]init]; //把操作添加到队列中 [queue addOperation:operation1]; [queue addOperation:operation2]; [queue addOperation:operation3]; } -(void)testOperation1 { for (int i = 0; i < 5; i++) { NSLog(@"-----NSInvocationOperation--1---- %@",[NSThread currentThread]); } } -(void)testOperation2 { for (int i = 0; i < 5; i++) { NSLog(@"-----NSInvocationOperation--2---- %@",[NSThread currentThread]); } } @end
打印结果:
2017-03-21 13:51:44.091 TestNSOperationQueue[5519:170579] -----NSBlockOperation----3--1---- <NSThread: 0x608000074f80>{number = 5, name = (null)} 2017-03-21 13:51:44.091 TestNSOperationQueue[5519:170582] -----NSInvocationOperation--2---- <NSThread: 0x608000075140>{number = 4, name = (null)} 2017-03-21 13:51:44.090 TestNSOperationQueue[5519:170580] -----NSInvocationOperation--1---- <NSThread: 0x60800006f200>{number = 3, name = (null)} 2017-03-21 13:51:44.091 TestNSOperationQueue[5519:170644] -----NSBlockOperation----3--2---- <NSThread: 0x6080000752c0>{number = 6, name = (null)} 2017-03-21 13:51:44.094 TestNSOperationQueue[5519:170579] -----NSBlockOperation----3--1---- <NSThread: 0x608000074f80>{number = 5, name = (null)} 2017-03-21 13:51:44.096 TestNSOperationQueue[5519:170580] -----NSInvocationOperation--1---- <NSThread: 0x60800006f200>{number = 3, name = (null)} 2017-03-21 13:51:44.096 TestNSOperationQueue[5519:170582] -----NSInvocationOperation--2---- <NSThread: 0x608000075140>{number = 4, name = (null)} 2017-03-21 13:51:44.099 TestNSOperationQueue[5519:170644] -----NSBlockOperation----3--2---- <NSThread: 0x6080000752c0>{number = 6, name = (null)} 2017-03-21 13:51:44.100 TestNSOperationQueue[5519:170579] -----NSBlockOperation----3--1---- <NSThread: 0x608000074f80>{number = 5, name = (null)} 2017-03-21 13:51:44.101 TestNSOperationQueue[5519:170580] -----NSInvocationOperation--1---- <NSThread: 0x60800006f200>{number = 3, name = (null)} 2017-03-21 13:51:44.103 TestNSOperationQueue[5519:170582] -----NSInvocationOperation--2---- <NSThread: 0x608000075140>{number = 4, name = (null)} 2017-03-21 13:51:44.103 TestNSOperationQueue[5519:170644] -----NSBlockOperation----3--2---- <NSThread: 0x6080000752c0>{number = 6, name = (null)} 2017-03-21 13:51:44.105 TestNSOperationQueue[5519:170579] -----NSBlockOperation----3--1---- <NSThread: 0x608000074f80>{number = 5, name = (null)} 2017-03-21 13:51:44.105 TestNSOperationQueue[5519:170580] -----NSInvocationOperation--1---- <NSThread: 0x60800006f200>{number = 3, name = (null)} 2017-03-21 13:51:44.106 TestNSOperationQueue[5519:170582] -----NSInvocationOperation--2---- <NSThread: 0x608000075140>{number = 4, name = (null)} 2017-03-21 13:51:44.108 TestNSOperationQueue[5519:170644] -----NSBlockOperation----3--2---- <NSThread: 0x6080000752c0>{number = 6, name = (null)} 2017-03-21 13:51:44.112 TestNSOperationQueue[5519:170579] -----NSBlockOperation----3--1---- <NSThread: 0x608000074f80>{number = 5, name = (null)} 2017-03-21 13:51:44.113 TestNSOperationQueue[5519:170580] -----NSInvocationOperation--1---- <NSThread: 0x60800006f200>{number = 3, name = (null)} 2017-03-21 13:51:44.117 TestNSOperationQueue[5519:170582] -----NSInvocationOperation--2---- <NSThread: 0x608000075140>{number = 4, name = (null)} 2017-03-21 13:51:44.119 TestNSOperationQueue[5519:170644] -----NSBlockOperation----3--2---- <NSThread: 0x6080000752c0>{number = 6, name = (null)}
实战: 实现一个下载图片的例子
// // ViewController.m // TestNSOperationQueue // // Created by taobaichi on 2017/3/21. // Copyright © 2017年 MaChao. All rights reserved. // #import "ViewController.h" #define kURL @"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg" @interface ViewController () @property (nonatomic, strong) UIImageView * imagView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.imagView = [[UIImageView alloc]initWithFrame:CGRectMake(self.view.frame.size.width/2 - 50, self.view.frame.size.height/2 - 50, 100, 100)]; self.imagView.backgroundColor = [UIColor lightGrayColor]; [self.view addSubview:self.imagView]; //创建一个后台线程,后台线程执行downloadImage方法 NSInvocationOperation * operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImage:) object:kURL]; //创建NSOperationQueue NSOperationQueue * queue = [[NSOperationQueue alloc]init]; //把创建的后台线程放到NSOperationQueue中 [queue addOperation:operation]; } -(void)downloadImage:(NSString *)url { NSLog(@"url: %@",url); NSURL * nsUrl = [NSURL URLWithString:url]; NSData * data = [[NSData alloc]initWithContentsOfURL:nsUrl]; UIImage * image = [[UIImage alloc]initWithData:data]; //下载完成后执行主线程updateUI方法 [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES]; } -(void)updateUI:(UIImage *)image { self.imagView.image = image; } @end
代码注释:
- viewDidLoad方法里可以看到我们用NSInvocationOperation建了一个后台线程,并且放到NSOperationQueue中。后台线程执行downloadImage方法。
- downloadImage 方法处理下载图片的逻辑。下载完成后用performSelectorOnMainThread执行主线程updateUI方法。
- updateUI 并把下载的图片显示到图片控件中。
运行后可以看到下载图片显示在界面上
Simulator Screen Shot 2017年3月21日 14.29.48.png