// ViewController.m #import "ViewController.h" @interface ViewController () { //任务队列,能够自动管理多个任务(NSOperation的对象) NSOperationQueue *_operationQueue; } @end @implementation ViewController #define kUrlString @"http://jsonfe.funshion.com/?pagesize=10&cli=iphone&page=1&src=phonemedia&ta=0&ver=1.2.8.2&jk=0" #define kImageString @"http://img1.funshion.com/attachment/fs/112/200/112200.jpg?1387939530" - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. _operationQueue = [[NSOperationQueue alloc] init]; UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [btn setTitle:@"thread" forState:UIControlStateNormal]; [btn setFrame:CGRectMake(10,30,300,50)]; [btn addTarget:self action:@selector(threadMethod) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn]; UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [btn1 setTitle:@"operation" forState:UIControlStateNormal]; [btn1 setFrame:CGRectMake(10,90,300,50)]; [btn1 addTarget:self action:@selector(operationMethod) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn1]; UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [btn2 setTitle:@"GCD" forState:UIControlStateNormal]; [btn2 setFrame:CGRectMake(10,150,300,50)]; [btn2 addTarget:self action:@selector(gcdMethod) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn2]; /*严重的费时操作 等好久才能显示 for (int i=0; i<20; i++) { for (int j=0; j<50; j++) { NSURL *url =[NSURL URLWithString:kImageString]; //同步下载数据的方法 NSData *data = [NSData dataWithContentsOfURL:url]; // UIImage *ima = [UIImage imageWithData:data]; UIImageView *ima=[[UIImageView alloc]initWithFrame:CGRectMake(0+j*3, i*3, 2, 2)]; ima.image=[UIImage imageWithData:data]; [self.view addSubview:ima]; } } */ } //gcd是iOS4.0之后出现的技术,Grand Centeral Dispatch->苹果高度封装的处理多线程的技术,可以理解为block版本的NSOperation和NSOperationQueue - (void)gcdMethod{ //gcd中有一个主队列,用于管理和调度主线程;有三个优先级的全局队列,来管理子线程 //dispatch_get_global_queue 第一个参数为设置队列的优先级 0为默认优先级 2为最高优先级 -1为低优先级;第二个参数为预留参数,一般也写成0 dispatch_async(dispatch_get_global_queue(0, 0), ^{ //利用全局队列,在主线程之外单独开辟了一个线程,线程执行block方法 NSURL *url =[NSURL URLWithString:kUrlString]; NSString *result = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil]; if (result) { //通过主队列回到主线程,主线程中执行block dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"result:%@",result); }); }else{ NSLog(@"error!"); } }); } //NSOperation,以任务为导向的线程,可以叫做开启一个任务 //NSOperationQueue 任务队列,来维护多个任务(线程) - (void)operationMethod{ //一般使用NSOperation的子类来进行多线程操作 NSInvocationOperation *oper = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage) object:nil]; //[oper start]; 需要调用此方法 oper对象才会开辟线程,让线程执行sel方法 //添加到队列后,队列会自动让oper对象开辟线程并执行sel方法 [_operationQueue addOperation:oper]; //[_operationQueue addOperations:<#(NSArray *)#> waitUntilFinished:<#(BOOL)#>] } //NSThread - (void)threadMethod{ //NSThread iOS中最早出现的线程类 //detachNewThreadSelector 在主线程之外单独开辟一个线程来执行sel方法 //toTarget sel所在的对象 [NSThread detachNewThreadSelector:@selector(downloadString) toTarget:self withObject:nil]; } //同步下载一张图片 - (void)downloadImage{ @autoreleasepool { NSURL *url =[NSURL URLWithString:kImageString]; //同步下载数据的方法 NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; if (image) { //给主线程 [self performSelectorOnMainThread:@selector(receiveImage:) withObject:image waitUntilDone:NO]; //线程之间的通信 //[self performSelector:<#(SEL)#> onThread:<#(NSThread *)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>] }else{ NSLog(@"下载失败!"); } } } - (void)receiveImage:(UIImage *)image{ //colorWithPatternImage 此方法比较消耗GPU,需要慎用,而且要求view与imagesize 一致 // self.view.backgroundColor = [UIColor colorWithPatternImage:image]; //多线程可以解决费时操作 比普通的下载图片快很多 for (int i=0; i<200; i++) { for (int j=0; j<500; j++) { UIImageView *ima=[[UIImageView alloc]init]; ima.frame=CGRectMake(0+j*30, i*30, 20, 20); ima.image=image; [self.view addSubview:ima]; } } } //线程的生命周期与函数一致,函数开始则线程开始;函数执行完毕,线程自动结束 //在主线程之外开辟的线程叫子线程或者工作线程 - (void)downloadString{ //执行耗时操作 //主线程的自动释放池,子线程无法使用,需要自己手动添加 @autoreleasepool { NSURL *url = [NSURL URLWithString:kUrlString]; //同步请求数据的方法,会阻塞当前线程 NSString *result = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil]; if (result) { //需要将数据给到UI主线程,理论上子线程没有被分配足够的资源来操作UI,所以对于UI的操作一般在主线程中完成。 //子线程和主线程之间的通信 [self performSelectorOnMainThread:@selector(receiveString:) withObject:result waitUntilDone:NO]; //[self performSelector:<#(SEL)#> withObject:<#(id)#>] }else{ NSLog(@"load error!"); } } } //在主线程中执行的方法 - (void)receiveString:(NSString *)result{ NSLog(@"ui result:%@",result); //操作UI也在主线程中 } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end