iOS: NSObject中执行Selector的相关方法
本文转载至 http://www.mgenware.com/blog/?p=463
1. 对当前Run Loop中Selector Sources的取消
NSObject中的performSelector:withObject:afterDelay:方法将会在当前线程的Run Loop中根据afterDelay参数创建一个Timer,如果没有调用有inModes参数的方法,该Timer会运行在当前Run Loop的默认模式中,也就是NSDefaultRunLoopMode定义的模式中。
performSelector:withObject:afterDelay:方法的使用看起来还是很简单的。这里讲另外一个辅助函数,NSObject中静态的cancelPreviousPerformRequestsWithTarget方法。该方法就是专门用来取消取消performSelector:withObject:afterDelay:方法所创建的Selector source(内部上就是一个Run Loop的Timer source)。因此该方法和performSelector:withObject:afterDelay:方法一样,只限于当前Run Loop中。
我们可以利用cancelPreviousPerformRequestsWithTarget直接取消一个对象在当前Run Loop中的所有未执行的performSelector:withObject:afterDelay:方法所产生的Selector Sources,如下代码:
- (void)viewDidLoad
{
[super viewDidLoad]; [self performSelector:@selector(test:) withObject:nil afterDelay:1];
[self performSelector:@selector(test:) withObject:@"mgen" afterDelay:2];
[NSObject cancelPreviousPerformRequestsWithTarget:self];
} - (void)test:(id)obj
{
NSLog(@"调用成功: %@", obj);
}
不会有任何输出,因为两个调用都被取消了。
如果想取消单独一个的话,需使用cancelPreviousPerformRequestsWithTarget:selector:object:方法,注意selector和object参数需要一一对应。如下代码:
- (void)viewDidLoad
{
[super viewDidLoad]; [self performSelector:@selector(test:) withObject:[NSNumber numberWithInt:26] afterDelay:1];
[self performSelector:@selector(test:) withObject:[NSNumber numberWithInt:17] afterDelay:2];
[self performSelector:@selector(test:) withObject:[NSNumber numberWithInt:17] afterDelay:3];
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(test:) object:[NSNumber numberWithInt:17]];
} - (void)test:(id)obj
{
NSLog(@"调用成功: %@", obj);
}
只会输出:
调用成功: 26
其他两个Selector都被取消了。
2. 在NSThread中执行Selector
这个话题很简单,直接通过NSObject的performSelectorInBackground:withObject:方法就可以,如下代码:
- (void)viewDidLoad
{
[super viewDidLoad]; [self threadInfo:@"UI"];
[self performSelectorInBackground:@selector(test:) withObject:nil]; } - (void)test:(id)obj
{
@autoreleasepool
{
[self threadInfo:@"test"];
}
}
- (void)threadInfo:(NSString*)category
{
NSLog(@"%@ - %@", category, [NSThread currentThread]);
}
输出:
UI - <NSThread: 0x71639e0>{name = (null), num = 1}
test - <NSThread: 0x7176ad0>{name = (null), num = 3}
这个方法完全等效于NSThread的detachNewThreadSelector:toTarget:withObject:静态方法,那么上面NSObject的performSelectorInBackground:withObject:方法调用完全可以替换成:
[NSThread detachNewThreadSelector:@selector(test:) toTarget:self withObject:nil];
当然,用户也可以自行手动创建一个NSThread来完成上述功能,代码如下:
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(test:) object:nil];
[thread start];
这两种方法运行后的输出是和第一种类似的。
3. 在NSThread中的Run Loop中执行Selector
这里需要的方法是NSObject的performSelector:onThread:withObject:waitUntilDone:方法。由于是在另一个NSThread中执行Selector,所以我们需要手动开始Run Loop。首先需要在ViewController中定义两个字段,分别是NSThread和控制线程内Run Loop执行的flag。
@interface ViewController ()
{
NSThread *_thread;
BOOL _isNewThreadAborted;
}
接下来做的是执行这个线程,并且在线程中手动调用NSRunLoop的runMode:beforeDate:方法。这里注意,如果Run Loop没有任何Source的话,该方法会立即返回,所以需要创建一个循环来持续调用Run Loop的runMode:beforeDate:方法。并在Selector执行结束后同时尝试结束这个循环。最终代码如下:
- (void)viewDidLoad
{
[super viewDidLoad]; [self threadInfo:@"UI"]; _isNewThreadAborted = NO;
_thread = [[NSThread alloc] initWithTarget:self selector:@selector(newThread:) object:nil];
//开始线程
[_thread start];
//在另一个线程中的Run Loop中执行Selector
[self performSelector:@selector(test:) onThread:_thread withObject:nil waitUntilDone:NO];
} //在新线程中创建并开始一个NSRunLoop
- (void)newThread:(id)obj
{
@autoreleasepool
{
NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
while (!_isNewThreadAborted)
{
[currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
NSLog(@"线程停止");
}
} //Selector执行
- (void)test:(id)obj
{
[self threadInfo:@"test"];
_isNewThreadAborted = YES;
} - (void)threadInfo:(NSString*)category
{
NSLog(@"%@ - %@", category, [NSThread currentThread]);
}
输出:
UI - <NSThread: 0x717e7e0>{name = (null), num = 1}
test - <NSThread: 0x8078a80>{name = (null), num = 3}
线程停止
最后注意performSelector:onThread:withObject:waitUntilDone:方法中最后的waitUntilDone参数,如果传YES的话,当前线程会等待Selector在另一个线程中执行完毕后继续执行。
iOS: NSObject中执行Selector的相关方法的更多相关文章
- NSObject 中执行Selector 的相关方法
1. 对当前Run Loop中Selector Sources的取消 NSObject中的performSelector:withObject:afterDelay:方法将会在当前线程的Run Loo ...
- iOS开发中方法延迟执行的几种方式
概述 项目开发中经常会用到方法的延时调用,下面列举常用的几种实现方式: 1.performSelector 2.NSTimer 3.NSThread线程的sleep 4.GCD 1.performSe ...
- 浅谈iOS开发中方法延迟执行的几种方式
Method1. performSelector方法 Method2. NSTimer定时器 Method3. NSThread线程的sleep Method4. GCD 公用延迟执行方法 - (vo ...
- iOS多线程中,队列和执行的排列组合结果分析
本文是对以往学习的多线程中知识点的一个整理. 多线程中的队列有:串行队列,并发队列,全局队列,主队列. 执行的方法有:同步执行和异步执行.那么两两一组合会有哪些注意事项呢? 如果不是在董铂然博客园看到 ...
- Java中子类和父类相关方法的执行顺序
无意中看到下面一个题目,大家一起来看看最后的输出结果是什么.反正我看完之后,用IDE测试后感觉知识点得到巩固了. /** * 函数执行顺序测试 * Created by 萌小Q on 2017/5/1 ...
- iOS多线程中performSelector: 和dispatch_time的不同
iOS中timer相关的延时调用,常见的有NSObject中的performSelector:withObject:afterDelay:这个方法在调用的时候会设置当前runloop中timer,还有 ...
- iOS开发中的4种数据持久化方式【二、数据库 SQLite3、Core Data 的运用】
在上文,我们介绍了ios开发中的其中2种数据持久化方式:属性列表.归档解档.本节将继续介绍另外2种iOS持久化数据的方法:数据库 SQLite3.Core Data 的运 ...
- iOS开发中的4种数据持久化方式【一、属性列表与归档解档】
iOS中的永久存储,也就是在关机重新启动设备,或者关闭应用时,不会丢失数据.在实际开发应用时,往往需要持久存储数据的,这样用户才能在对应用进行操作后,再次启动能看到自己更改的结果与痕迹.ios开发中, ...
- 多线程技术在iOS开发中的使用
进程和线程 要使用多线程,首先需要理解进程和线程这2个概念.这里我简单的说一下. 所谓进程对应的是一个应用程序,负责开辟内存空间供应用程序使用,但是进程不能执行任务(指令).一个进程至少包含一条线程, ...
随机推荐
- 心智图/思维导图(Mind Map/Mind Mapping),思维导图介绍
心智图(Mind Map),又称脑图.心智地图.脑力激荡图.思维导图.灵感触发图.概念地图.树状图.树枝图或思维地图,是一种图像式思维的工具以及一种利用图像式思考辅助工具来表达思维的工具. 心智图 ...
- C#指南,重温基础,展望远方!(10)C#枚举
枚举类型是包含一组已命名常量的独特值类型. 需要定义包含一组离散值的类型时,可以定义枚举. 枚举使用一种整型值类型作为其基础存储, 并提供离散值的语义含义. 以下示例声明并使用名为“Color”的 e ...
- WinForm下的键盘事件(KeyPress、KeyDown)及如何处理不响应键盘事件
KeyDown事件用来处理功能键:F1 F2 F3... keyPress事件用来处理字符比如说:A B C... 1 2 3... 注:处理该事件时,需要先将窗体的 KeyPreview=true; ...
- 一名全栈工程师Node.js之路-转
Node.js 全球现状 虽然 Node.js 在国内没有盛行,但据 StackOverflow 2016 年开发者调查,其中 node.js .全栈.JavaScript 相关的技术在多个领域(包括 ...
- MySQL EXPLAIN 命令详解
MySQL EXPLAIN 命令详解 MySQL的EXPLAIN命令用于SQL语句的查询执行计划(QEP).这条命令的输出结果能够让我们了解MySQL 优化器是如何执行SQL 语句的.这条命令并没有提 ...
- sso单点登录研究
iframe跨域通信的通用解决方案http://www.alloyteam.com/2012/08/lightweight-solution-for-an-iframe-cross-domain-co ...
- COM方式实现C++调用C#代码的一些总结
首先这个测试没成功,只在本机上可行,在不同机器上测试失败.可能是GUID不对或者没注册成功. 既然已经花了一上午时间去研究,还是总结一下 1.网上说要创建一个snk证书,但不创建也可以.只不过不能放入 ...
- Atitit.软件GUI按钮与仪表盘(01)--js区-----js格式化的使用
Atitit.软件GUI按钮与仪表盘(01)--js区-----js格式化的使用 1. Chrome36( recomm) DEV TOOL>SOURCE> DSWEIHAMYAR &q ...
- oracle 使用occi方式 批量插入多条数据
if (vecInfo.empty()) { ; //数据为空,不上传,不上传标志设置为1,只有0表示上传成功 } std::string strUserName = userName; std::s ...
- NFC读卡APP
# 设计文档 ### 简介----------------------------- 这个APP的功能是使用手机的NFC读卡器功能,做到读取卡片支持M1卡和CPU卡. ### 功能列表-------- ...