1 使用NSThread实现打地鼠
1.1 问题
NSThread是ios提供的轻量级的多线程解决方案,但是需要自己管理线程的生命周期、线程同步等。本案例使用NSThread实现一个打地鼠的小游戏,在界面随机产生mouse(继承至UIButton),以及点击mouse消失得分等功能,如图-1所示:
图-1
1.2 方案
首先创建一个SingleViewApplication应用,在该应用中创建一个TRMouse地鼠类,由于地鼠具有点击功能,因此TRMouse类继承至UIButton。
其次在TRMouse的初始化方法中将背景设置为红色,标题设置为3,并添加点击事件当地鼠出现在界面三秒钟之内被点击即消失得分。
地鼠出现三秒钟没有被点击则自动消失,所以TRMouse类中需要使用detachNewThreadSelector:toTarget:withObject:方法开一个线程用于计时,每隔一秒调用一次refresh方法,地鼠的标题进行三、二、一倒计时显示,最后从界面消失。
然后在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方法中开启一个线程,用于定时调用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) {
- count = 3;
- self.backgroundColor = [UIColorredColor];
- [selfsetTitle:[NSStringstringWithFormat:@"%d",count] forState:UIControlStateNormal];
- [selfaddTarget:self action:@selector(clicked) forControlEvents:UIControlEventTouchUpInside];
- }
- return self;
- }
实现clicked方法,代码如下所示:
- - (void)clicked {
- [selfremoveFromSuperview];
- self.tag = 1;
- }
地鼠出现三秒钟没有被点击则自动消失,所以TRMouse类中需要使用detachNewThreadSelector:toTarget:withObject:方法开一个线程用于计时,每隔一秒调用一次refresh方法,地鼠的标题进行三、二、一倒计时显示,最后从界面消失,代码如下所示:
- - (id)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- if (self) {
- count = 3;
- self.backgroundColor = [UIColorredColor];
- [selfsetTitle:[NSStringstringWithFormat:@"%d",count] forState:UIControlStateNormal];
- [selfaddTarget:self action:@selector(clicked) forControlEvents:UIControlEventTouchUpInside];
- }
- [NSThreaddetachNewThreadSelector:@selector(refresh) toTarget:selfwithObject:nil];
- return self;
- }
- //实现refresh方法
- - (void)refresh {
- for(inti=0;i<4;i++) {
- [selfperformSelectorOnMainThread:@selector(mouseDisapear) withObject:nilwaitUntilDone:NO];
- [NSThread sleepForTimeInterval:1];
- }
- }
- //实现mouseDisappear方法
- -(void)mouseDisapear {
- self.titleLabel.text =[NSStringstringWithFormat:@"%d",count];
- NSLog(@"count = %d",count);
- if (count==0&&self.tag!=1) {
- [selfremoveFromSuperview];
- }
- count--;
- }
步骤二:添加成功标签和失败标签
首先在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];
- }
- //失败自动消失
- -(void)mouseDisapear {
- self.titleLabel.text =[NSStringstringWithFormat:@"%d",count];
- NSLog(@"count = %d",count);
- if (count==0&&self.tag!=1) {
- [selfremoveFromSuperview];
- [self.delegatechangeScoreWithSuccess:NO];
- }
- count--;
- }
步骤三:搭建界面
首先在ViewController类的viewDidLoad方法中开启一个线程,用于定时调用addMouse方法产生地鼠对象,然后返回主线程将产生的地鼠对象添加到界面,代码如下所示:
- - (void)viewDidLoad {
- [superviewDidLoad];
- [NSThreaddetachNewThreadSelector:@selector(addMouse) toTarget:selfwithObject:nil];
- }
- - (void)addMouse {
- for (inti=0;;i++) {
- [NSThread sleepForTimeInterval:1];
- [selfperformSelectorOnMainThread:@selector(addMouseView) withObject:nilwaitUntilDone:NO];
- }
- }
- - (void)addMouseView {
- 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)addMouseView {
- 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];
- [NSThreaddetachNewThreadSelector:@selector(addMouse) toTarget:selfwithObject:nil];
- }
- - (void)addMouse {
- for (inti=0;;i++) {
- [NSThread sleepForTimeInterval:1];
- [selfperformSelectorOnMainThread:@selector(addMouseView) withObject:nilwaitUntilDone:NO];
- }
- }
- - (void)addMouseView {
- 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 (){
- int count;
- }
- @end
- @implementationTRMouse
- - (id)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- if (self) {
- count = 3;
- self.backgroundColor = [UIColorredColor];
- [selfsetTitle:[NSStringstringWithFormat:@"%d",count] forState:UIControlStateNormal];
- [selfaddTarget:self action:@selector(clicked) forControlEvents:UIControlEventTouchUpInside];
- }
- [NSThreaddetachNewThreadSelector:@selector(refresh) toTarget:selfwithObject:nil];
- return self;
- }
- - (void)clicked {
- [selfremoveFromSuperview];
- self.tag = 1;
- [self.delegatechangeScoreWithSuccess:YES];
- }
- - (void)refresh {
- for(inti=0;i<4;i++) {
- [selfperformSelectorOnMainThread:@selector(mouseDisapear) withObject:nilwaitUntilDone:NO];
- [NSThread sleepForTimeInterval:1];
- }
- }
- -(void)mouseDisapear {
- self.titleLabel.text =[NSStringstringWithFormat:@"%d",count];
- NSLog(@"count = %d",count);
- if (count==0&&self.tag!=1) {
- [selfremoveFromSuperview];
- [self.delegatechangeScoreWithSuccess:NO];
- }
- count--;
- }
- @end