码迷,mamicode.com
首页 > 其他好文 > 详细

GCD

时间:2015-12-15 22:48:34      阅读:329      评论:0      收藏:0      [点我收藏+]

标签:

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,并添加点击事件当地鼠出现在界面三秒钟之内被点击即消失,代码如下所示:

 
  1. - (id)initWithFrame:(CGRect)frame
  2. {
  3. self = [super initWithFrame:frame];
  4. if (self) {
  5. self.backgroundColor = [UIColorredColor];
  6. [selfsetTitle:@"3" forState:UIControlStateNormal];
  7. [selfaddTarget:self action:@selector(clicked) forControlEvents:UIControlEventTouchUpInside];
  8. }
  9. return self;
  10. }

实现clicked方法,代码如下所示:

  1. - (void)clicked {
  2. [selfremoveFromSuperview];
  3. self.tag = 1;
  4. }

地鼠出现三秒钟没有被点击则自动消失,所以TRMouse类中需要使用dispatch_queue_create函数创建一个调度队列并且异步执行,每秒钟对地鼠的标题进行三、二、一倒计时修改,最后从界面消失从主线程上将地鼠移除父视图,代码如下所示:

 
  1. - (id)initWithFrame:(CGRect)frame
  2. {
  3. self = [super initWithFrame:frame];
  4. if (self) {
  5. self.backgroundColor = [UIColorredColor];
  6. [selfsetTitle:@"3" forState:UIControlStateNormal];
  7. [selfaddTarget:self action:@selector(clicked) forControlEvents:UIControlEventTouchUpInside];
  8. }
  9. dispatch_queue_t queue = dispatch_queue_create("queue", NULL);
  10. dispatch_async(queue, ^{
  11. for(inti=2;i>=0;i--) {
  12. [NSThread sleepForTimeInterval:1];
  13. dispatch_async(dispatch_get_main_queue(), ^{
  14. self.titleLabel.text =[NSStringstringWithFormat:@"%d",i];
  15. });
  16. }
  17. if (self.tag!=1) {
  18. dispatch_async(dispatch_get_main_queue(), ^{
  19. [selfremoveFromSuperview];
  20. });
  21. }
  22. });
  23. return self;
  24. }

步骤二:添加成功标签和失败标签

首先在Storyboard的场景中拖放两个Label分别用于显示成功的计数和失败的计数,并关联成ViewController的输出口属性successLabel和failLabel,代码如下所示:

  1. @interfaceViewController ()
  2. @property (weak, nonatomic) IBOutletUILabel *successLabel;
  3. @property (weak, nonatomic) IBOutletUILabel *failLabel;
  4. @end

当成功点击地鼠时成功计数加一,地鼠自动消失失败计数加一,该功能可以通过委托协议来实现,在TRMouse类中定义一个TRMouseDelegate协议,该协议有一个需要实现的方法-(void)changeScoreWithSuccess:(BOOL)isSuccess,代码如下所示:

 
  1. @protocolTRMouseDelegate
  2. -(void)changeScoreWithSuccess:(BOOL)isSuccess;
  3. @end

再在TRMouse类中定义一个公开的属性id<TRMouseDelegate>delegate,用于指定委托对象,代码如下所示:

 
  1. @interfaceTRMouse : UIButton
  2. @property (nonatomic,assign) id<TRMouseDelegate> delegate;
  3. @end

最后在成功点击地鼠消失方法中delegate调用changeScoreWithSuccess:方法isSuccess参数传入YES,在地鼠自动消失的方法delegate调用changeScoreWithSuccess:方法isSuccess参数传入NO,代码如下所示:

 
  1. //成功点击
  2. - (void)clicked {
  3. [selfremoveFromSuperview];
  4. self.tag = 1;
  5. [self.delegatechangeScoreWithSuccess:YES];
  6. }
  7. //失败自动消失
  8. - (id)initWithFrame:(CGRect)frame
  9. {
  10. self = [super initWithFrame:frame];
  11. if (self) {
  12. self.backgroundColor = [UIColorredColor];
  13. [selfsetTitle:@"3" forState:UIControlStateNormal];
  14. [selfaddTarget:self action:@selector(clicked) forControlEvents:UIControlEventTouchUpInside];
  15. }
  16. dispatch_queue_t queue = dispatch_queue_create("queue", NULL);
  17. dispatch_async(queue, ^{
  18. for(inti=2;i>=0;i--) {
  19. [NSThread sleepForTimeInterval:1];
  20. dispatch_async(dispatch_get_main_queue(), ^{
  21. self.titleLabel.text =[NSStringstringWithFormat:@"%d",i];
  22. });
  23. }
  24. if (self.tag!=1) {
  25. dispatch_async(dispatch_get_main_queue(), ^{
  26. [selfremoveFromSuperview];
  27. [self.delegatechangeScoreWithSuccess:NO];
  28. });
  29. }
  30. });
  31. return self;
  32. }

步骤三:搭建界面

首先在ViewController类的viewDidLoad方法中使用dispatch_queue_create函数创建一个调度队列并且异步执行,用于定时调用addMouse方法产生地鼠对象,然后返回主队列将产生的地鼠对象添加到界面,代码如下所示:

  1. - (void)viewDidLoad {
  2. [superviewDidLoad];
  3. dispatch_queue_tmyQueue = dispatch_queue_create("myQueue", NULL);
  4. dispatch_async(myQueue, ^{
  5. for (inti=0;;i++) {
  6. [NSThread sleepForTimeInterval:1];
  7. dispatch_async(dispatch_get_main_queue(), ^{
  8. CGSizescreenSize = [[UIScreenmainScreen]bounds].size;
  9. TRMouse *mouse = [[TRMousealloc]initWithFrame:CGRectMake(arc4random()%(int)(screenSize.width-30), 50+arc4random()%(int)(screenSize.height-80), 30, 30)];
  10. [self.viewaddSubview:mouse];
  11. });
  12. }
  13. });
  14. }

然后ViewController类遵守TRMouseDelegate协议,在创建TRMouse对象时将delegate指定为ViewController,代码如下所示:

 
  1. - (void)viewDidLoad {
  2. [superviewDidLoad];
  3. dispatch_queue_tmyQueue = dispatch_queue_create("myQueue", NULL);
  4. dispatch_async(myQueue, ^{
  5. for (inti=0;;i++) {
  6. [NSThread sleepForTimeInterval:1];
  7. dispatch_async(dispatch_get_main_queue(), ^{
  8. CGSizescreenSize = [[UIScreenmainScreen]bounds].size;
  9. TRMouse *mouse = [[TRMousealloc]initWithFrame:CGRectMake(arc4random()%(int)(screenSize.width-30), 50+arc4random()%(int)(screenSize.height-80), 30, 30)];
  10. mouse.delegate = self;
  11. [self.viewaddSubview:mouse];
  12. });
  13. }
  14. });
  15. }

最后ViewController实现changeScoreWithSuccess:方法,根据isSucces参数修改successLabel和failLabel的显示内容:

  1. -(void)changeScoreWithSuccess:(BOOL)isSuccess {
  2. switch ((int)isSuccess) {
  3. case 0:{
  4. int count = [self.failLabel.textintValue];
  5. self.failLabel.text = [NSStringstringWithFormat:@"%d",++count];
  6. }
  7. break;
  8. case 1:{
  9. int count = [self.successLabel.textintValue];
  10. self.successLabel.text = [NSStringstringWithFormat:@"%d",++count];
  11. }
  12. }
  13. }

1.4 完整代码

本案例中,ViewController.m文件中的完整代码如下所示:

 
  1. #import "ViewController.h"
  2. @interfaceViewController () <TRMouseDelegate>
  3. @property (weak, nonatomic) IBOutletUILabel *successLabel;
  4. @property (weak, nonatomic) IBOutletUILabel *failLabel;
  5. @end
  6. @implementationViewController
  7. - (void)viewDidLoad {
  8. [superviewDidLoad];
  9. dispatch_queue_tmyQueue = dispatch_queue_create("myQueue", NULL);
  10. dispatch_async(myQueue, ^{
  11. for (inti=0;;i++) {
  12. [NSThread sleepForTimeInterval:1];
  13. dispatch_async(dispatch_get_main_queue(), ^{
  14. CGSizescreenSize = [[UIScreenmainScreen]bounds].size;
  15. TRMouse *mouse = [[TRMousealloc]initWithFrame:CGRectMake(arc4random()%(int)(screenSize.width-30), 50+arc4random()%(int)(screenSize.height-80), 30, 30)];
  16. mouse.delegate = self;
  17. [self.viewaddSubview:mouse];
  18. });
  19. }
  20. });
  21. }
  22. -(void)changeScoreWithSuccess:(BOOL)isSuccess {
  23. switch ((int)isSuccess) {
  24. case 0:{
  25. int count = [self.failLabel.textintValue];
  26. self.failLabel.text = [NSStringstringWithFormat:@"%d",++count];
  27. }
  28. break;
  29. case 1:{
  30. int count = [self.successLabel.textintValue];
  31. self.successLabel.text = [NSStringstringWithFormat:@"%d",++count];
  32. }
  33. }
  34. }
  35. @end
 

本案例中,TRMouse.h文件中的完整代码如下所示:

 
  1. #import<UIKit/UIKit.h>
  2. @protocolTRMouseDelegate
  3. -(void)changeScoreWithSuccess:(BOOL)isSuccess;
  4. @end
  5. @interfaceTRMouse : UIButton
  6. @property (nonatomic,assign) id<TRMouseDelegate> delegate;
  7. @end
 

本案例中,TRMouse.m文件中的完整代码如下所示:

 
  1. #import "TRMouse.h"
  2. @interfaceTRMouse ()
  3. @end
  4. @implementationTRMouse
  5. - (id)initWithFrame:(CGRect)frame
  6. {
  7. self = [super initWithFrame:frame];
  8. if (self) {
  9. self.backgroundColor = [UIColorredColor];
  10. [selfsetTitle:@"3" forState:UIControlStateNormal];
  11. [selfaddTarget:self action:@selector(clicked) forControlEvents:UIControlEventTouchUpInside];
  12. }
  13. dispatch_queue_t queue = dispatch_queue_create("queue", NULL);
  14. dispatch_async(queue, ^{
  15. for(inti=2;i>=0;i--) {
  16. [NSThread sleepForTimeInterval:1];
  17. dispatch_async(dispatch_get_main_queue(), ^{
  18. self.titleLabel.text =[NSStringstringWithFormat:@"%d",i];
  19. });
  20. }
  21. if (self.tag!=1) {
  22. dispatch_async(dispatch_get_main_queue(), ^{
  23. [selfremoveFromSuperview];
  24. [self.delegatechangeScoreWithSuccess:NO];
  25. });
  26. }
  27. });
  28. return self;
  29. }
  30. - (void)clicked {
  31. [selfremoveFromSuperview];
  32. self.tag = 1;
  33. [self.delegatechangeScoreWithSuccess:YES];
  34. }
  35. @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,代码如下所示:

 
  1. +(NSMutableArray *)getImageUrlByWeb:(NSString *)url{
  2. NSMutableArray *imageUrls = [NSMutableArray array];
  3. NSStringEncodingenc = CFStringConvertEncodingToNSStringEncoding (kCFStringEncodingGB_18030_2000);
  4. NSString *html = [NSStringstringWithContentsOfURL:[NSURL URLWithString:url] encoding:encerror:nil];
  5. NSLog(@"%@",html);
  6. NSArray *arr = [html componentsSeparatedByString:@"\""];
  7. for (NSString *str in arr) {
  8. if ([strhasSuffix:@"jpg"]) {
  9. if ([strrangeOfString:@"logo"].length>0) {
  10. continue;
  11. }
  12. [imageUrlsaddObject:str];
  13. }
  14. }
  15. returnimageUrls;
  16. }

步骤二:开启线程获取网络图片的url

在Storyboard中拖放一个ScrollView控件并关联成ViewController的输出口属性showImages,代码如下所示:

 
  1. @interfaceViewController ()
  2. @property (weak, nonatomic) IBOutletUIScrollView *showImages;
  3. @end

再在ViewDidLoad方法中开启一个线程通过Utils的getImageUrlByWeb:方法获取图片的url,代码如下所示:

 
  1. - (void)viewDidLoad
  2. {
  3. [superviewDidLoad];
  4. NSMutableArray *urls = [NSMutableArray array];
  5. dispatch_queue_t q1 = dispatch_queue_create("", nil);
  6. dispatch_async(q1, ^{
  7. for (inti=1; i<50; i++) {
  8. [urlsaddObjectsFromArray: [UtilsgetImageUrlByWeb:[NSString stringWithFormat:@"http://wallpaper.pconline.com.cn/list/1_%d_des1.html",i]]];
  9. }
  10. });
  11. }

步骤三:开启线程获取图片数据

依次访问图片的url获取图片数据,由于获取图片这是一个耗时操作所以需要再开启一个线程,然后回到主界面展示图片,代码如下所示:

 
  1. -(void)download:(NSMutableArray *)urls{
  2. [self.showImagessetContentSize:CGSizeMake(320, 80*((urls.count/4)+1))];
  3. dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);
  4. for (inti=0; i<urls.count; i++) {
  5. NSString *imageUrl = [urlsobjectAtIndex:i];
  6. dispatch_async(queue, ^{
  7. NSData *data = [NSDatadataWithContentsOfURL:[NSURL URLWithString:imageUrl]];
  8. dispatch_async(dispatch_get_main_queue(), ^{
  9. UIImageView *iv = [[UIImageViewalloc]initWithFrame:CGRectMake(i%4*80, i/4*80, 80, 80)];
  10. iv.alpha = 0;
  11. iv.image = [UIImageimageWithData:data];
  12. [self.showImagesaddSubview:iv];
  13. [UIViewbeginAnimations:nilcontext:nil];
  14. [UIView setAnimationDuration:.5];
  15. [UIViewsetAnimationCurve:UIViewAnimationCurveEaseIn];
  16. iv.alpha = 1;
  17. [UIViewcommitAnimations];
  18. });
  19. });
  20. }
  21. }

2.4 完整代码

本案例中,ViewController.m文件中的完整代码如下所示:

 
  1. #import "ViewController.h"
  2. #import "Utils.h"
  3. @interfaceViewController ()
  4. @property (weak, nonatomic) IBOutletUIScrollView *showImages;
  5. @end
  6. @implementationViewController
  7. - (void)viewDidLoad
  8. {
  9. [superviewDidLoad];
  10. NSMutableArray *urls = [NSMutableArray array];
  11. dispatch_queue_t q1 = dispatch_queue_create("", nil);
  12. dispatch_async(q1, ^{
  13. for (inti=1; i<50; i++) {
  14. [urlsaddObjectsFromArray: [UtilsgetImageUrlByWeb:[NSString stringWithFormat:@"http://wallpaper.pconline.com.cn/list/1_%d_des1.html",i]]];
  15. }
  16. NSLog(@"%d",urls.count);
  17. [selfdownload:urls];
  18. });
  19. }
  20. -(void)download:(NSMutableArray *)urls{
  21. [self.showImagessetContentSize:CGSizeMake(320, 80*((urls.count/4)+1))];
  22. dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);
  23. for (inti=0; i<urls.count; i++) {
  24. NSString *imageUrl = [urlsobjectAtIndex:i];
  25. dispatch_async(queue, ^{
  26. NSData *data = [NSDatadataWithContentsOfURL:[NSURL URLWithString:imageUrl]];
  27. dispatch_async(dispatch_get_main_queue(), ^{
  28. UIImageView *iv = [[UIImageViewalloc]initWithFrame:CGRectMake(i%4*80, i/4*80, 80, 80)];
  29. iv.alpha = 0;
  30. iv.image = [UIImageimageWithData:data];
  31. [self.showImagesaddSubview:iv];
  32. [UIViewbeginAnimations:nilcontext:nil];
  33. [UIView setAnimationDuration:.5];
  34. [UIViewsetAnimationCurve:UIViewAnimationCurveEaseIn];
  35. iv.alpha = 1;
  36. [UIViewcommitAnimations];
  37. });
  38. });
  39. }
  40. }
  41. @end
 

本案例中,Utils.m文件中的完整代码如下所示:

 
  1. #import "Utils.h"
  2. @implementationUtils
  3. +(NSMutableArray *)getImageUrlByWeb:(NSString *)url{
  4. NSMutableArray *imageUrls = [NSMutableArray array];
  5. NSStringEncodingenc = CFStringConvertEncodingToNSStringEncoding (kCFStringEncodingGB_18030_2000);
  6. NSString *html = [NSStringstringWithContentsOfURL:[NSURL URLWithString:url] encoding:encerror:nil];
  7. NSLog(@"%@",html);
  8. NSArray *arr = [html componentsSeparatedByString:@"\""];
  9. for (NSString *str in arr) {
  10. if ([strhasSuffix:@"jpg"]) {
  11. if ([strrangeOfString:@"logo"].length>0) {
  12. continue;
  13. }
  14. [imageUrlsaddObject:str];
  15. }
  16. }
  17. returnimageUrls;
  18. }
  19. @end

GCD

标签:

原文地址:http://www.cnblogs.com/52190112cn/p/5049551.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!