performSelector:target:argument:order:modes:和cancelPerformSelector:target:argument:的使用

今天在研究一个框架的时候,发现对方使用了cancelPerformSelector:target:argument:这个方法,遂打开文档研究了一下。

performSelector:target:argument:order:modes:和cancelPerformSelector:target:argument:是

NSRunLoop的一个叫NSOrderedPerform的Category中定义的两个方法。顾名思义,order有顺序的意思,即按某种顺序执行方法,没错,这个顺序方法就是performSelector:target:argument:order:modes:,这个方法的作用是按照参数order来先后执行target对象的方法,argument和modes分别是参数和运行循环的模式,这个分类还相应的有一个配套的取消方法,就是cancelPerformSelector:target:argument:,作用就是取消要执行的selector参数,注意,上面的selector都是target的方法,argument都是target的参数,如果误代可能会引起奔溃。

显然,既然它们都是NSRunLoop的方法,那么,它们必须要在某条开启运行循环的线程中使用才有效。下面我们来测试一下:新建一个project,接着运行下面的代码:

[[NSRunLoop currentRunLoop]performSelector:@selector(doTip) target:self argument:nil order:0 modes:@[(NSRunLoopMode)kCFRunLoopDefaultMode]];
- (void)doTip {
    NSLog(@"%s", __func__);
}
运行之后控制器打印
接着,我们把代码改成
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [[NSRunLoop currentRunLoop]performSelector:@selector(doTip) target:self argument:nil order:0 modes:@[(NSRunLoopMode)kCFRunLoopDefaultMode]];
});

运行,控制台毫无反应。

为什么之前的代码可以而这段代码不行?

这是因为,之前的代码是默认在主线乘中执行的,而主线程在被创建之后就已经开启运行循环,而在这段代码中我们使用全局队列,但是并没有开启队列中线程的运行循环,所以我们需要把代码补齐,把这段代码改为

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  
  NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
  [runLoop addPort:[NSPort port] forMode:(NSRunLoopMode)kCFRunLoopCommonModes];
  [runLoop performSelector:@selector(doTip) target:self argument:nil order:10 modes:@[(NSRunLoopMode)kCFRunLoopCommonModes]];
  [runLoop run];
});
再次运行,控制台又有输出了。
之前说过,performSelector:target:argument:order:modes:和顺序有关,在这里参数order是一个NSUInteger类型,那是什么顺序,这里我们也测试一下,

更换代码:

[[NSRunLoop currentRunLoop]performSelector:@selector(doTip5) target:self argument:nil order:5 modes:@[(NSRunLoopMode)kCFRunLoopDefaultMode]];
[[NSRunLoop currentRunLoop]performSelector:@selector(doTip2) target:self argument:nil order:2 modes:@[(NSRunLoopMode)kCFRunLoopDefaultMode]];
[[NSRunLoop currentRunLoop]performSelector:@selector(doTip3) target:self argument:nil order:3 modes:@[(NSRunLoopMode)kCFRunLoopDefaultMode]];
[[NSRunLoop currentRunLoop]performSelector:@selector(doTip1) target:self argument:nil order:1 modes:@[(NSRunLoopMode)kCFRunLoopDefaultMode]];
[[NSRunLoop currentRunLoop]performSelector:@selector(doTip4) target:self argument:nil order:4 modes:@[(NSRunLoopMode)kCFRunLoopDefaultMode]];

- (void)doTip1 {
    NSLog(@"%s", __func__);
}
- (void)doTip2 {
    NSLog(@"%s", __func__);
}
- (void)doTip3 {
    NSLog(@"%s", __func__);
}
- (void)doTip4 {
    NSLog(@"%s", __func__);
}
- (void)doTip5 {
    NSLog(@"%s", __func__);
}
运行:






我们仔细观察代码的书写顺序和运行结果就会发现,参数order越小,执行越早,也就是说,最早执行的代码是order最小的那个,然后按顺序进行下去。个人觉得这个方法真是强大。

接下去我们讲它的配对,取消执行方法:cancelPerformSelector:target:argument:

直接上代码:

[[NSRunLoop currentRunLoop]performSelector:@selector(doTip) target:self argument:nil order:1 modes:@[(NSRunLoopMode)kCFRunLoopDefaultMode]];
[[NSRunLoop currentRunLoop] cancelPerformSelector:@selector(doTip) target:self argument:nil];
运行:

控制台啥都没有!

没错,cancelPerformSelector:target:argument:直接把performSelector:target:argument:order:modes:要执行的selector给取消了,就这样没了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值