线程之间的通信
我们在iOS开发中使用多线程一般使用这几种,NSThread,GCD,NSOperation;
我们多在自线程中进行数据加载或者下载的操作,所以总免不了将获取到的数据发送到主线程进行显示或者进行操作,下面就是我们经常使用基本的线程之间的通信;
项目的准备工作:
1.新建一个Xcode项目,在storybo
ard中创建一个image View,并设置约束和image view控件的大小,
关联到viewController的( @property (weak, nonatomic) IBOutlet UIImageView *imageview;)属性;
2.在子线程下载的图片,然后显示到image view上;
第一种:NSThread
-(void)thread{ // 创建一个字符串 NSString *str = @"http://www.xiami.com/images/collect/802/2/10023802_1330239346.jpg"; [self performSelectorInBackground:@selector(loadImage:) withObject:str]; } -(void)loadImage:(NSString *)str{ NSURL *url = [NSURL URLWithString:str]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; NSLog(@"loadImage----->%@",[NSThread currentThread]); /** * 这个方法回到主线程并且执行 * @param updateUI: 执行更新ui的方法 */ [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:NO]; } -(void)updateUI:(UIImage *)image{ self.imageview.image = image; }
触发thread方法,performSelectorInBackground:withObject: ---->方法开启一个子线程,在子线程中执行 loadImage: 的方法,在loadImage中下载图片,然后调用performSelectorOnMainThread:withObject;回到主线程,在updateUI中将下载好的图片赋值给imageView;
第二种:GCD
//调用gcd
-(void)gcd{ NSString *str = @"http://www.xiami.com/images/collect/802/2/10023802_1330239346.jpg";
//在下面这个block使用self会形成循环引用,使用__weak修饰weakSelf,可以放置循环引用; //控制器对block有一个强引用,如果在block中使用self的话,block也对控制器有一个强引用; __weak typeof(self) weakSelf = self; /** * 开启一个异步任务, * 获取一个全局队列,在全局队列中下载图片 * 开启一个异步任务,在这个异步任务中获取一个主队列,在主队列中更新ui; */ dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSURL *url = [NSURL URLWithString:str]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; dispatch_async(dispatch_get_main_queue(), ^{ weakSelf.imageview.image = image; }); }); }
这个例子使用了两个简单的异步任务组合全局队列和主队列,进行下载操作和更新ui的操作;
第三种:NSoperation
创建继承 NSOperation的文件,
DownLoadOperation.h
// DownLoadOperation.h // 线程之间的通信 // // Created by 两好三坏 on 16/2/21. // Copyright © 2016年 qinakun. All rights reserved. // #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> typedef void(^FinishBlock)(UIImage *image); @interface DownLoadOperation : NSOperation //图片地址 @property(nonatomic,copy) NSString *imageUrl; @property(nonatomic,copy) FinishBlock finishBlock; @end
DownLoadOperation.m
// // DownLoadOperation.m // 线程之间的通信 // // Created by 两好三坏 on 16/2/21. // Copyright © 2016年 qinakun. All rights reserved. // #import "DownLoadOperation.h" @implementation DownLoadOperation -(void)main{ @autoreleasepool { //1.1.拿着imageURLString去网络上下载 NSURL *url = [NSURL URLWithString:self.imageUrl]; //1.2.去网络上加载图片 NSData *imageData = [NSData dataWithContentsOfURL:url]; //1.3.将我们从网络上获取到的图片的二进制,转成UIImage UIImage *image = [UIImage imageWithData:imageData]; if (self.finishBlock) { self.finishBlock(image); } } } @end
在控制器中的代码如下
-(void)operation{ DownLoadOperation *operation = [DownLoadOperation new]; operation.imageUrl = @"http://www.xiami.com/images/collect/802/2/10023802_1330239346.jpg"; // 使用block, operation.finishBlock = ^(UIImage *image){ __weak typeof(self) weakSelf = self; [[NSOperationQueue mainQueue] addOperationWithBlock:^{ weakSelf.imageview.image = image; }]; }; }