线程和NSThread 、 NSOperation

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

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

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

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

地鼠出现三秒钟没有被点击则自动消失,所以TRMouse类中需要使用detachNewThreadSelector:toTarget:withObject:方法开一个线程用于计时,每隔一秒调用一次refresh方法,地鼠的标题进行三、二、一倒计时显示,最后从界面消失,代码如下所示:

  1. - (id)initWithFrame:(CGRect)frame
  2. {
  3. self = [super initWithFrame:frame];
  4. if (self) {
  5. count = 3;
  6. self.backgroundColor = [UIColorredColor];
  7. [selfsetTitle:[NSStringstringWithFormat:@"%d",count] forState:UIControlStateNormal];
  8. [selfaddTarget:self action:@selector(clicked) forControlEvents:UIControlEventTouchUpInside];
  9. }
  10. [NSThreaddetachNewThreadSelector:@selector(refresh) toTarget:selfwithObject:nil];
  11. return self;
  12. }
  13. //实现refresh方法
  14. - (void)refresh {
  15. for(inti=0;i<4;i++) {
  16. [selfperformSelectorOnMainThread:@selector(mouseDisapear) withObject:nilwaitUntilDone:NO];
  17. [NSThread sleepForTimeInterval:1];
  18. }
  19. }
  20. //实现mouseDisappear方法
  21. -(void)mouseDisapear {
  22. self.titleLabel.text =[NSStringstringWithFormat:@"%d",count];
  23. NSLog(@"count = %d",count);
  24. if (count==0&&self.tag!=1) {
  25. [selfremoveFromSuperview];
  26. }
  27. count--;
  28. }

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

首先在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. -(void)mouseDisapear {
  9. self.titleLabel.text =[NSStringstringWithFormat:@"%d",count];
  10. NSLog(@"count = %d",count);
  11. if (count==0&&self.tag!=1) {
  12. [selfremoveFromSuperview];
  13. [self.delegatechangeScoreWithSuccess:NO];
  14. }
  15. count--;
  16. }

步骤三:搭建界面

首先在ViewController类的viewDidLoad方法中开启一个线程,用于定时调用addMouse方法产生地鼠对象,然后返回主线程将产生的地鼠对象添加到界面,代码如下所示:

  1. - (void)viewDidLoad {
  2. [superviewDidLoad];
  3. [NSThreaddetachNewThreadSelector:@selector(addMouse) toTarget:selfwithObject:nil];
  4. }
  5. - (void)addMouse {
  6. for (inti=0;;i++) {
  7. [NSThread sleepForTimeInterval:1];
  8. [selfperformSelectorOnMainThread:@selector(addMouseView) withObject:nilwaitUntilDone:NO];
  9. }
  10. }
  11. - (void)addMouseView {
  12. CGSizescreenSize = [[UIScreenmainScreen]bounds].size;
  13. TRMouse *mouse = [[TRMousealloc]initWithFrame:CGRectMake(arc4random()%(int)(screenSize.width-30), 50+arc4random()%(int)(screenSize.height-80), 30, 30)];
  14. [self.viewaddSubview:mouse];
  15. }

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

  1. - (void)addMouseView {
  2. CGSizescreenSize = [[UIScreenmainScreen]bounds].size;
  3. TRMouse *mouse = [[TRMousealloc]initWithFrame:CGRectMake(arc4random()%(int)(screenSize.width-30), 50+arc4random()%(int)(screenSize.height-80), 30, 30)];
  4. mouse.delegate = self;
  5. [self.viewaddSubview:mouse];
  6. }

最后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. [NSThreaddetachNewThreadSelector:@selector(addMouse) toTarget:selfwithObject:nil];
  10. }
  11. - (void)addMouse {
  12. for (inti=0;;i++) {
  13. [NSThread sleepForTimeInterval:1];
  14. [selfperformSelectorOnMainThread:@selector(addMouseView) withObject:nilwaitUntilDone:NO];
  15. }
  16. }
  17. - (void)addMouseView {
  18. CGSizescreenSize = [[UIScreenmainScreen]bounds].size;
  19. TRMouse *mouse = [[TRMousealloc]initWithFrame:CGRectMake(arc4random()%(int)(screenSize.width-30), 50+arc4random()%(int)(screenSize.height-80), 30, 30)];
  20. mouse.delegate = self;
  21. [self.viewaddSubview:mouse];
  22. }
  23. -(void)changeScoreWithSuccess:(BOOL)isSuccess {
  24. switch ((int)isSuccess) {
  25. case 0:{
  26. int count = [self.failLabel.textintValue];
  27. self.failLabel.text = [NSStringstringWithFormat:@"%d",++count];
  28. }
  29. break;
  30. case 1:{
  31. int count = [self.successLabel.textintValue];
  32. self.successLabel.text = [NSStringstringWithFormat:@"%d",++count];
  33. }
  34. }
  35. }
  36. @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. int count;
  4. }
  5. @end
  6. @implementationTRMouse
  7. - (id)initWithFrame:(CGRect)frame
  8. {
  9. self = [super initWithFrame:frame];
  10. if (self) {
  11. count = 3;
  12. self.backgroundColor = [UIColorredColor];
  13. [selfsetTitle:[NSStringstringWithFormat:@"%d",count] forState:UIControlStateNormal];
  14. [selfaddTarget:self action:@selector(clicked) forControlEvents:UIControlEventTouchUpInside];
  15. }
  16. [NSThreaddetachNewThreadSelector:@selector(refresh) toTarget:selfwithObject:nil];
  17. return self;
  18. }
  19. - (void)clicked {
  20. [selfremoveFromSuperview];
  21. self.tag = 1;
  22. [self.delegatechangeScoreWithSuccess:YES];
  23. }
  24. - (void)refresh {
  25. for(inti=0;i<4;i++) {
  26. [selfperformSelectorOnMainThread:@selector(mouseDisapear) withObject:nilwaitUntilDone:NO];
  27. [NSThread sleepForTimeInterval:1];
  28. }
  29. }
  30. -(void)mouseDisapear {
  31. self.titleLabel.text =[NSStringstringWithFormat:@"%d",count];
  32. NSLog(@"count = %d",count);
  33. if (count==0&&self.tag!=1) {
  34. [selfremoveFromSuperview];
  35. [self.delegatechangeScoreWithSuccess:NO];
  36. }
  37. count--;
  38. }
  39. @end
时间: 2024-11-17 02:07:28

线程和NSThread 、 NSOperation的相关文章

iOS 多线程 NSThread NSOperation NSOperationQueue GCD 线程锁 线程阻塞

iPhone中的线程应用并不是无节制的,官方给出的资料显示,iPhone OS下的主线程的堆栈大小是1M,第二个线程开始就是512KB,并且该值不能通过编译器开关或线程API函数来更改,只有主线程有直接修改UI的能力,所以一些数据层面可以开辟线程来操作进行,iOS线程的操作方法有NSThread NSOperation NSOperationQueue GCD: NSThread方法有 //NSThread自动 - (IBAction)didClickNSThreadAutoButtonActi

多线程之pthread, NSThread, NSOperation, GCD

关于多线程会有一系列如下:多线程之概念解析 多线程之pthread, NSThread, NSOperation, GCD 多线程之NSThread 多线程之NSOperation 多线程之GCD pthread:跨平台,适用于多种操作系统,可移植性强,是一套纯C语言的通用API,且线程的生命周期需要程序员自己管理,使用难度较大,所以在实际开发中通常不使用. NThread:是苹果对pthread的一个封装.通过封装可以在Cocoa环境中,可以更简易地用多线程.线程的生命周期由程序员管理.每个N

多线程&amp;NSObject&amp;NSThread&amp;NSOperation&amp;GCD

1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 以下两点是苹果专门开发的“并发”技术,使得程序员可以不再去关心线程的具体使用问题 2.NSOperation/NSOperationQueue 面向对象的线程技术 3.GCD —— Grand Central Dispatch(派发) 是基于C语言的框架,可以充分利用多核,是苹果推荐使用的多线程技术 以上这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的.但是就目

iOS并发编程对比总结,NSThread,NSOperation,GCD - iOS

1. 多线程概念 进程 正在进行中的程序被称为进程,负责程序运行的内存分配 每一个进程都有自己独立的虚拟内存空间 线程 线程是进程中一个独立的执行路径(控制单元) 一个进程中至少包含一条线程,即主线程 可以将耗时的执行路径(如:网络请求)放在其他线程中执行 创建线程的目的就是为了开启一条新的执行路径,运行指定的代码,与主线程中的代码实现同时运行 1.1 多任务系统调度示意图 说明:每个应用程序由操作系统分配的短暂的时间片(Timeslice)轮流使用CPU,由于CPU对每个时间片的处理速度非常快

iOS多线程入门之NSThread,NSOperation,GCD

一 线程的概念 一个运行着的程序就是一个进程或者叫做一个任务,一个进程至少包含一个线程,线程就是程序的执行流.Mac和iOS中的程序启动,创建好一个进程的同时, 一个线程便开始运行,这个线程叫主线程.主线程在程序中的地位和其他线程不同,它是其他线程最终的父线程,且所有界面的显示操作即AppKit或 UIKit的操作必须在主线程进行. 系统中的每一个进程都有自己独立的虚拟内存空间,而同一个进程中的多个线程则共用进程的内存空间.每创建一个新的线程,都需要一些内存(如每个线程有自己的Stack空间)和

IOS-线程操作之NSThread/NSOperation

1NSThread.声明线程,启动线程:(第一个参数声明了目标类,第2个参数声明了目标方法,第3个参数为该方法的参数) NSThread *thread=[[NSThread alloc] initWithTarget:selfselector:@selector(saleTicketMethod:) object:@"线程--1"]; [thread start]; 2.IOS跟Android一样都是线程不安全的 也就是所有UI更新都必须在主线程内完成,这样,当我们在另一条线程中想要

四、线程管理————NSThread

1.创建新线程的三种方式,例如: NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo:) object:nil];[thread start];[NSThread detachNewThreadSelector:@selector(demo:) toTarget:self withObject:nil];    [self performSelectorInBackground:@sel

iOS-多线程--(pthread/NSThread/GCD/NSOperation)--总结

零.线程的注意点(掌握)1.不要同时开太多的线程(1~3条线程即可,不要超过5条)2.线程概念1> 主线程 : UI线程,显示.刷新UI界面,处理UI控件的事件2> 子线程 : 后台线程,异步线程3.不要把耗时的操作放在主线程,要放在子线程中执行 一.NSThread(掌握)1.创建和启动线程的3种方式1> 先创建,后启动// 创建NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(dow

iOS多线程开发--NSThread NSOperation GCD

多线程 当用户播放音频.下载资源.进行图像处理时往往希望做这些事情的时候其他操作不会被中 断或者希望这些操作过程中更加顺畅.在单线程中一个线程只能做一件事情,一件事情处理不完另一件事就不能开始,这样势必影响用户体验.早在单核处理器时期 就有多线程,这个时候多线程更多的用于解决线程阻塞造成的用户等待(通常是操作完UI后用户不再干涉,其他线程在等待队列中,CPU一旦空闲就继续执行, 不影响用户其他UI操作),其处理能力并没有明显的变化.如今无论是移动操作系统还是PC.服务器都是多核处理器,于是“并行