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:方法,注意selectorobject参数需要一一对应。如下代码:

- (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

这个话题很简单,直接通过NSObjectperformSelectorInBackground: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}

这个方法完全等效于NSThreaddetachNewThreadSelector:toTarget:withObject:静态方法,那么上面NSObjectperformSelectorInBackground: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

这里需要的方法是NSObjectperformSelector:onThread:withObject:waitUntilDone:方法。由于是在另一个NSThread中执行Selector,所以我们需要手动开始Run Loop。首先需要在ViewController中定义两个字段,分别是NSThread和控制线程内Run Loop执行的flag。

@interface ViewController ()
{
NSThread *_thread;
BOOL _isNewThreadAborted;
}

接下来做的是执行这个线程,并且在线程中手动调用NSRunLooprunMode: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在另一个线程中执行完毕后继续执行。

4. UIPinchGestureRecognizer 与 NSObject Selector 的关联

if (recognizer.state == UIGestureRecognizerStateChanged) {

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(XXXSetNeedsDisplay) object:recognizer];

    // 相关的方法...

} else if (recognizer.state == UIGestureRecognizerStateEnded) {

[self performSelector:@selector(XXXSetNeedsDisplay) withObject:recognizer afterDelay:1.0f];

}

NSObject 中执行Selector 的相关方法的更多相关文章

  1. iOS: NSObject中执行Selector的相关方法

    本文转载至 http://www.mgenware.com/blog/?p=463 1. 对当前Run Loop中Selector Sources的取消 NSObject中的performSelect ...

  2. Java中子类和父类相关方法的执行顺序

    无意中看到下面一个题目,大家一起来看看最后的输出结果是什么.反正我看完之后,用IDE测试后感觉知识点得到巩固了. /** * 函数执行顺序测试 * Created by 萌小Q on 2017/5/1 ...

  3. NIO[读]、[写]在同一线程(单线程)中执行,让CPU使用率最大化,提高处理效率

    前几天写过一篇文章,讨论重写服务后,用ab进行压力测试,发现使用NIO后没提高什么性能,只是CPU使用率提高了,内存占用降低了. 之前的NIO实现模式,主要参考(基于事件的NIO多线程服务器)http ...

  4. Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理

    Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理 转自:https://www.jianshu.com/p/2b71ea919d49 本系列文章首发于我的个人博 ...

  5. Object-C 中的Selector 概念

    selector可以叫做选择器,其实指的就是对象的方法,也可以理解为C语言里面的函数指针,在面向对象里面的对应概念. @selector(xxxx)的作用是找到名字为xxxx的方法.一般用于[a pe ...

  6. Java I/O(4):AIO和NIO中的Selector

    您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来- 在Java NIO的三大核心中,除了Channel和Buffer,剩下的就是Selector了.有的地方叫它选择器,也有叫多路复用器的(比如Ne ...

  7. 【Win 10 应用开发】在App所在的进程中执行后台任务

    在以往版本中,后台任务都是以独立的专用进程来运行,因此,定义后台任务代码的类型都要位于 Windows 运行时组件项目中. 不过,在14393中,SDK 作了相应的扩展,不仅支持以前的独立进程中运行后 ...

  8. [C#] 走进异步编程的世界 - 在 GUI 中执行异步操作

    走进异步编程的世界 - 在 GUI 中执行异步操作 [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5877042.html 序 这是继<开始接 ...

  9. 【python之路2】CMD中执行python程序中文显示乱码

    在IDLE中执行下面代码,中文显示正常: # -*- coding:utf-8 -*- st=raw_input("请输入内容")print st 但在CMD中执行e:\hello ...

随机推荐

  1. 根据车辆品牌获取品牌所属公司,车标logo,创建年份等基本信息

    接口:http://api.besttool.cn/?c=Car&a=brand 请求方式:post 参数: appid 请联系博主QQ987332767获取,注明车标接口,测试appid: ...

  2. webkit 控件供vb 6 调用,不错~

    https://groups.google.com/forum/#!topic/microsoft.public.vb.general.discussion/ZaFY95aDZoY http://ww ...

  3. 第六章 Windows应用程序对键盘与鼠标的响应 P121 6-8

    基于键盘与鼠标应用的程序设计 一.实验目的 1.掌握键盘与鼠标在应用程序中的消息响应机制.   二.实验内容及步骤 实验任务 1.熟悉键盘的消息响应: 2.熟悉鼠标的消息响应: 实验内容 设计一个窗口 ...

  4. code1167 树网的核

    floyd+枚举 看点: 1.floyd同时用数组p记录转移节点k,这样知道线段的端点u v就可以得到整条线段 2.任意一点c到线段a b的距离=(d[a][c]+d[c][b]-d[a][b])/2 ...

  5. 1.oracle dblink(数据库不同实例数据对导)

    .创建一个两个数据库之间的dblink,语法如下 create database link to_test connect to scott identified by tiger using '(D ...

  6. Python中的排序方法sort(),sorted(),argsort()等

    python 列表排序方法sort.sorted技巧篇 转自https://www.cnblogs.com/whaben/p/6495702.html,学习参考. Python list内置sort( ...

  7. linux源码安装php7.2.0

    1. 源码包下载地址 2. 解压php压缩包 tar –zxvf php-7.2.0.tar.gz 3. 进入解压后的 cd php7.2.0 4.安装php需要的扩展 yum install lib ...

  8. URAL 1996 Cipher Message 3 (FFT + KMP)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题意 :给出两个串A , B,每个串是若干个byt ...

  9. DATASNAP远程方法返回TSTREAM正解

    DATASNAP远程方法返回TSTREAM正解 DATASNAP远程方法返回TSTREAM,如果数据大小超过32K是会报错的.许多DELPHIER栽在这个上头,甚至开始怀疑TSTREAM返回数据的可行 ...

  10. (转)最全正则表达式总结:验证QQ号、手机号、Email、中文、邮编、身份证、IP地址等

    什么是 RegExp? RegExp 是正则表达式(Regular expression)的缩写,作用是对字符串执行模式匹配. 通常用于格式验证.正则替换.查找子串等 各种编程语言的正则表达式基本相同 ...