• GCD


    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
  • 相关阅读:
    vuex之store拆分即多模块状态管理
    vue项目中使用vueX
    vue中父子组件的参数传递和应用
    VUE中使用vue-awesome-swiper
    VUE真实项目中常用的生命周期和参数
    VUE生命周期
    vue+mockjs 模拟数据,请求回调的应用
    Vue项目搭建与部署还有调试插件Vue.js devtools
    tableTD中添加对角斜线
    前端面试题及答案,理论知识
  • 原文地址:https://www.cnblogs.com/52190112cn/p/5049551.html
Copyright © 2020-2023  润新知