1 使用GCD实现打地鼠
1.1 问题
GCD是Grand Central Dispatch中央任务分发中心的简称,是苹果公司为多核的并行运算提出的解决方案。GCD在工作时会自动利用更多的处理器核心,以充分利用更强大的机器,它是基于C语言的API。本案例使用GCD实现打地鼠小游戏,在界面随机产生mouse(继承至UIButton),以及点击mouse消失得分等功能,如图-1所示:
图-1
1.2 方案
首先创建一个SingleViewApplication应用,在该应用中创建一个TRMouse地鼠类,由于地鼠具有点击功能,因此TRMouse类继承至UIButton。
其次在TRMouse的初始化方法中将背景设置为红色,标题设置为3,并添加点击事件当地鼠出现在界面三秒钟之内被点击即消失得分。
地鼠出现三秒钟没有被点击则自动消失,所以TRMouse类中需要使用dispatch_queue_create函数创建一个调度队列并且异步执行,每秒钟对地鼠的标题进行三、二、一倒计时修改,最后从界面消失。
然后在Storyboard的场景中拖放两个Label分别用于显示成功的计数和失败的计数,并关联成ViewController的输出口属性successLabel和failLabel。
当成功点击地鼠时成功计数加一,地鼠自动消失失败计数加一,该功能可以通过委托协议来实现,在TRMouse类中定义一个TRMouseDelegate协议,该协议有一个需要实现的方法-(void)changeScoreWithSuccess:(BOOL)isSuccess。再在TRMouse类中定义一个公开的属性id<TRMouseDelegate>delegate,用于指定委托对象。在成功点击地鼠消失方法中delegate调用changeScoreWithSuccess:方法isSuccess参数传入YES,在地鼠自动消失的方法delegate调用changeScoreWithSuccess:方法isSuccess参数传入NO。
最后在ViewController类的viewDidLoad方法中使用dispatch_queue_create函数创建一个调度队列并且异步执行,用于定时调用addMouse方法产生地鼠对象,然后返回主队列将产生的地鼠对象添加到界面。
ViewController类遵守TRMouseDelegate协议,在创建TRMouse对象时将delegate指定为ViewController。ViewController实现changeScoreWithSuccess:方法,根据isSucces参数修改successLabel和failLabel的显示内容。
1.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:创建地鼠类TRMouse
首先创建一个SingleViewApplication应用,在该应用中创建一个TRMouse地鼠类,由于地鼠具有点击功能,因此TRMouse类继承至UIButton,如图-2所示:
图-2
其次在TRMouse的初始化方法中将背景设置为红色,标题设置为3,并添加点击事件当地鼠出现在界面三秒钟之内被点击即消失,代码如下所示:
- - (id)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- if (self) {
- self.backgroundColor = [UIColorredColor];
- [selfsetTitle:@"3" forState:UIControlStateNormal];
- [selfaddTarget:self action:@selector(clicked) forControlEvents:UIControlEventTouchUpInside];
- }
- return self;
- }
实现clicked方法,代码如下所示:
- - (void)clicked {
- [selfremoveFromSuperview];
- self.tag = 1;
- }
地鼠出现三秒钟没有被点击则自动消失,所以TRMouse类中需要使用dispatch_queue_create函数创建一个调度队列并且异步执行,每秒钟对地鼠的标题进行三、二、一倒计时修改,最后从界面消失从主线程上将地鼠移除父视图,代码如下所示:
- - (id)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- if (self) {
- self.backgroundColor = [UIColorredColor];
- [selfsetTitle:@"3" forState:UIControlStateNormal];
- [selfaddTarget:self action:@selector(clicked) forControlEvents:UIControlEventTouchUpInside];
- }
- dispatch_queue_t queue = dispatch_queue_create("queue", NULL);
- dispatch_async(queue, ^{
- for(inti=2;i>=0;i--) {
- [NSThread sleepForTimeInterval:1];
- dispatch_async(dispatch_get_main_queue(), ^{
- self.titleLabel.text =[NSStringstringWithFormat:@"%d",i];
- });
- }
- if (self.tag!=1) {
- dispatch_async(dispatch_get_main_queue(), ^{
- [selfremoveFromSuperview];
- });
- }
- });
- return self;
- }
步骤二:添加成功标签和失败标签
首先在Storyboard的场景中拖放两个Label分别用于显示成功的计数和失败的计数,并关联成ViewController的输出口属性successLabel和failLabel,代码如下所示:
- @interfaceViewController ()
- @property (weak, nonatomic) IBOutletUILabel *successLabel;
- @property (weak, nonatomic) IBOutletUILabel *failLabel;
- @end
当成功点击地鼠时成功计数加一,地鼠自动消失失败计数加一,该功能可以通过委托协议来实现,在TRMouse类中定义一个TRMouseDelegate协议,该协议有一个需要实现的方法-(void)changeScoreWithSuccess:(BOOL)isSuccess,代码如下所示:
- @protocolTRMouseDelegate
- -(void)changeScoreWithSuccess:(BOOL)isSuccess;
- @end
再在TRMouse类中定义一个公开的属性id<TRMouseDelegate>delegate,用于指定委托对象,代码如下所示:
- @interfaceTRMouse : UIButton
- @property (nonatomic,assign) id<TRMouseDelegate> delegate;
- @end
最后在成功点击地鼠消失方法中delegate调用changeScoreWithSuccess:方法isSuccess参数传入YES,在地鼠自动消失的方法delegate调用changeScoreWithSuccess:方法isSuccess参数传入NO,代码如下所示:
- - (void)clicked {
- [selfremoveFromSuperview];
- self.tag = 1;
- [self.delegatechangeScoreWithSuccess:YES];
- }
- - (id)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- if (self) {
- self.backgroundColor = [UIColorredColor];
- [selfsetTitle:@"3" forState:UIControlStateNormal];
- [selfaddTarget:self action:@selector(clicked) forControlEvents:UIControlEventTouchUpInside];
- }
- dispatch_queue_t queue = dispatch_queue_create("queue", NULL);
- dispatch_async(queue, ^{
- for(inti=2;i>=0;i--) {
- [NSThread sleepForTimeInterval:1];
- dispatch_async(dispatch_get_main_queue(), ^{
- self.titleLabel.text =[NSStringstringWithFormat:@"%d",i];
- });
- }
- if (self.tag!=1) {
- dispatch_async(dispatch_get_main_queue(), ^{
- [selfremoveFromSuperview];
- [self.delegatechangeScoreWithSuccess:NO];
- });
- }
- });
- return self;
- }
步骤三:搭建界面
首先在ViewController类的viewDidLoad方法中使用dispatch_queue_create函数创建一个调度队列并且异步执行,用于定时调用addMouse方法产生地鼠对象,然后返回主队列将产生的地鼠对象添加到界面,代码如下所示:
- - (void)viewDidLoad {
- [superviewDidLoad];
- dispatch_queue_tmyQueue = dispatch_queue_create("myQueue", NULL);
- dispatch_async(myQueue, ^{
- for (inti=0;;i++) {
- [NSThread sleepForTimeInterval:1];
- dispatch_async(dispatch_get_main_queue(), ^{
- CGSizescreenSize = [[UIScreenmainScreen]bounds].size;
- TRMouse *mouse = [[TRMousealloc]initWithFrame:CGRectMake(arc4random()%(int)(screenSize.width-30), 50+arc4random()%(int)(screenSize.height-80), 30, 30)];
- [self.viewaddSubview:mouse];
- });
- }
- });
- }
然后ViewController类遵守TRMouseDelegate协议,在创建TRMouse对象时将delegate指定为ViewController,代码如下所示:
- - (void)viewDidLoad {
- [superviewDidLoad];
- dispatch_queue_tmyQueue = dispatch_queue_create("myQueue", NULL);
- dispatch_async(myQueue, ^{
- for (inti=0;;i++) {
- [NSThread sleepForTimeInterval:1];
- dispatch_async(dispatch_get_main_queue(), ^{
- CGSizescreenSize = [[UIScreenmainScreen]bounds].size;
- TRMouse *mouse = [[TRMousealloc]initWithFrame:CGRectMake(arc4random()%(int)(screenSize.width-30), 50+arc4random()%(int)(screenSize.height-80), 30, 30)];
- mouse.delegate = self;
- [self.viewaddSubview:mouse];
- });
- }
- });
- }
最后ViewController实现changeScoreWithSuccess:方法,根据isSucces参数修改successLabel和failLabel的显示内容:
- -(void)changeScoreWithSuccess:(BOOL)isSuccess {
- switch ((int)isSuccess) {
- case 0:{
- int count = [self.failLabel.textintValue];
- self.failLabel.text = [NSStringstringWithFormat:@"%d",++count];
- }
- break;
- case 1:{
- int count = [self.successLabel.textintValue];
- self.successLabel.text = [NSStringstringWithFormat:@"%d",++count];
- }
- }
- }
1.4 完整代码
本案例中,ViewController.m文件中的完整代码如下所示:
- #import "ViewController.h"
- @interfaceViewController () <TRMouseDelegate>
- @property (weak, nonatomic) IBOutletUILabel *successLabel;
- @property (weak, nonatomic) IBOutletUILabel *failLabel;
- @end
- @implementationViewController
- - (void)viewDidLoad {
- [superviewDidLoad];
- dispatch_queue_tmyQueue = dispatch_queue_create("myQueue", NULL);
- dispatch_async(myQueue, ^{
- for (inti=0;;i++) {
- [NSThread sleepForTimeInterval:1];
- dispatch_async(dispatch_get_main_queue(), ^{
- CGSizescreenSize = [[UIScreenmainScreen]bounds].size;
- TRMouse *mouse = [[TRMousealloc]initWithFrame:CGRectMake(arc4random()%(int)(screenSize.width-30), 50+arc4random()%(int)(screenSize.height-80), 30, 30)];
- mouse.delegate = self;
- [self.viewaddSubview:mouse];
- });
- }
- });
- }
- -(void)changeScoreWithSuccess:(BOOL)isSuccess {
- switch ((int)isSuccess) {
- case 0:{
- int count = [self.failLabel.textintValue];
- self.failLabel.text = [NSStringstringWithFormat:@"%d",++count];
- }
- break;
- case 1:{
- int count = [self.successLabel.textintValue];
- self.successLabel.text = [NSStringstringWithFormat:@"%d",++count];
- }
- }
- }
- @end
本案例中,TRMouse.h文件中的完整代码如下所示:
- #import<UIKit/UIKit.h>
- @protocolTRMouseDelegate
- -(void)changeScoreWithSuccess:(BOOL)isSuccess;
- @end
- @interfaceTRMouse : UIButton
- @property (nonatomic,assign) id<TRMouseDelegate> delegate;
- @end
本案例中,TRMouse.m文件中的完整代码如下所示:
- #import "TRMouse.h"
- @interfaceTRMouse ()
- @end
- @implementationTRMouse
- - (id)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- if (self) {
- self.backgroundColor = [UIColorredColor];
- [selfsetTitle:@"3" forState:UIControlStateNormal];
- [selfaddTarget:self action:@selector(clicked) forControlEvents:UIControlEventTouchUpInside];
- }
- dispatch_queue_t queue = dispatch_queue_create("queue", NULL);
- dispatch_async(queue, ^{
- for(inti=2;i>=0;i--) {
- [NSThread sleepForTimeInterval:1];
- dispatch_async(dispatch_get_main_queue(), ^{
- self.titleLabel.text =[NSStringstringWithFormat:@"%d",i];
- });
- }
- if (self.tag!=1) {
- dispatch_async(dispatch_get_main_queue(), ^{
- [selfremoveFromSuperview];
- [self.delegatechangeScoreWithSuccess:NO];
- });
- }
- });
- return self;
- }
- - (void)clicked {
- [selfremoveFromSuperview];
- self.tag = 1;
- [self.delegatechangeScoreWithSuccess:YES];
- }
- @end
2 使用GCD实现图片的异步下载
2.1 问题
本案例使用GCD实现图片的异步下载,边下载边将图片显示在界面上,如图-3所示:
图-3
2.2 方案
首先创建一个SingleViewApplication应用,在该应用中创建一个Utils类用于获取网络图片的url,该类有一个静态方法getImageUrlByWeb:,该方法通过一个网页的url获取网页html文件,再通过字符串的的分割获取到图片的url。
然后在Storyboard中拖放一个ScrollView控件并关联成ViewController的输出口属性showImages。再在ViewDidLoad方法中开启一个线程通过Utils的getImageUrlByWeb:方法获取图片的url。
最后依次访问图片的url获取图片数据,由于获取图片这是一个耗时操作所以需要再开启一个线程,然后回到主界面展示图片。
2.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:获取网络图片的url
首先创建一个SingleViewApplication应用,在该应用中创建一个Utils类用于获取网络图片的url,该类有一个静态方法getImageUrlByWeb:,该方法通过一个网页的url获取网页html文件,再通过字符串的的分割获取到图片的url,代码如下所示:
- +(NSMutableArray *)getImageUrlByWeb:(NSString *)url{
- NSMutableArray *imageUrls = [NSMutableArray array];
- NSStringEncodingenc = CFStringConvertEncodingToNSStringEncoding (kCFStringEncodingGB_18030_2000);
- NSString *html = [NSStringstringWithContentsOfURL:[NSURL URLWithString:url] encoding:encerror:nil];
- NSLog(@"%@",html);
- NSArray *arr = [html componentsSeparatedByString:@"\""];
- for (NSString *str in arr) {
- if ([strhasSuffix:@"jpg"]) {
- if ([strrangeOfString:@"logo"].length>0) {
- continue;
- }
- [imageUrlsaddObject:str];
- }
- }
- returnimageUrls;
- }
步骤二:开启线程获取网络图片的url
在Storyboard中拖放一个ScrollView控件并关联成ViewController的输出口属性showImages,代码如下所示:
- @interfaceViewController ()
- @property (weak, nonatomic) IBOutletUIScrollView *showImages;
- @end
再在ViewDidLoad方法中开启一个线程通过Utils的getImageUrlByWeb:方法获取图片的url,代码如下所示:
- - (void)viewDidLoad
- {
- [superviewDidLoad];
- NSMutableArray *urls = [NSMutableArray array];
- dispatch_queue_t q1 = dispatch_queue_create("", nil);
- dispatch_async(q1, ^{
- for (inti=1; i<50; i++) {
- [urlsaddObjectsFromArray: [UtilsgetImageUrlByWeb:[NSString stringWithFormat:@"http://wallpaper.pconline.com.cn/list/1_%d_des1.html",i]]];
- }
- });
- }
步骤三:开启线程获取图片数据
依次访问图片的url获取图片数据,由于获取图片这是一个耗时操作所以需要再开启一个线程,然后回到主界面展示图片,代码如下所示:
- -(void)download:(NSMutableArray *)urls{
- [self.showImagessetContentSize:CGSizeMake(320, 80*((urls.count/4)+1))];
- dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);
- for (inti=0; i<urls.count; i++) {
- NSString *imageUrl = [urlsobjectAtIndex:i];
- dispatch_async(queue, ^{
- NSData *data = [NSDatadataWithContentsOfURL:[NSURL URLWithString:imageUrl]];
- dispatch_async(dispatch_get_main_queue(), ^{
- UIImageView *iv = [[UIImageViewalloc]initWithFrame:CGRectMake(i%4*80, i/4*80, 80, 80)];
- iv.alpha = 0;
- iv.image = [UIImageimageWithData:data];
- [self.showImagesaddSubview:iv];
- [UIViewbeginAnimations:nilcontext:nil];
- [UIView setAnimationDuration:.5];
- [UIViewsetAnimationCurve:UIViewAnimationCurveEaseIn];
- iv.alpha = 1;
- [UIViewcommitAnimations];
- });
- });
- }
- }
2.4 完整代码
本案例中,ViewController.m文件中的完整代码如下所示:
- #import "ViewController.h"
- #import "Utils.h"
- @interfaceViewController ()
- @property (weak, nonatomic) IBOutletUIScrollView *showImages;
- @end
- @implementationViewController
- - (void)viewDidLoad
- {
- [superviewDidLoad];
- NSMutableArray *urls = [NSMutableArray array];
- dispatch_queue_t q1 = dispatch_queue_create("", nil);
- dispatch_async(q1, ^{
- for (inti=1; i<50; i++) {
- [urlsaddObjectsFromArray: [UtilsgetImageUrlByWeb:[NSString stringWithFormat:@"http://wallpaper.pconline.com.cn/list/1_%d_des1.html",i]]];
- }
- NSLog(@"%d",urls.count);
- [selfdownload:urls];
- });
- }
- -(void)download:(NSMutableArray *)urls{
- [self.showImagessetContentSize:CGSizeMake(320, 80*((urls.count/4)+1))];
- dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);
- for (inti=0; i<urls.count; i++) {
- NSString *imageUrl = [urlsobjectAtIndex:i];
- dispatch_async(queue, ^{
- NSData *data = [NSDatadataWithContentsOfURL:[NSURL URLWithString:imageUrl]];
- dispatch_async(dispatch_get_main_queue(), ^{
- UIImageView *iv = [[UIImageViewalloc]initWithFrame:CGRectMake(i%4*80, i/4*80, 80, 80)];
- iv.alpha = 0;
- iv.image = [UIImageimageWithData:data];
- [self.showImagesaddSubview:iv];
- [UIViewbeginAnimations:nilcontext:nil];
- [UIView setAnimationDuration:.5];
- [UIViewsetAnimationCurve:UIViewAnimationCurveEaseIn];
- iv.alpha = 1;
- [UIViewcommitAnimations];
- });
- });
- }
- }
- @end
本案例中,Utils.m文件中的完整代码如下所示:
- #import "Utils.h"
- @implementationUtils
- +(NSMutableArray *)getImageUrlByWeb:(NSString *)url{
- NSMutableArray *imageUrls = [NSMutableArray array];
- NSStringEncodingenc = CFStringConvertEncodingToNSStringEncoding (kCFStringEncodingGB_18030_2000);
- NSString *html = [NSStringstringWithContentsOfURL:[NSURL URLWithString:url] encoding:encerror:nil];
- NSLog(@"%@",html);
- NSArray *arr = [html componentsSeparatedByString:@"\""];
- for (NSString *str in arr) {
- if ([strhasSuffix:@"jpg"]) {
- if ([strrangeOfString:@"logo"].length>0) {
- continue;
- }
- [imageUrlsaddObject:str];
- }
- }
- returnimageUrls;
- }
- @end