NSTimer、performSelector 函数没有被调用的原因

performSelector 指定的方法没有被调用

Invokes a method of the receiver on the current thread using the default mode after a delay.

根据苹果的文档,performSelector:withObject:afterDelay: 在指定时间之后,在当前线程 调用一个方法。如果这个线程在指定时间之后不存在了,自然也就不会调用这个方法了。
一个例子如下:
声明一个manager,里面有一个串行的队列,并在初始化方法中调用 performSelector:withObject:afterDelay: 方法。

- (instancetype)init
{
    if (self = [super init])
    {
        _queue = dispatch_queue_create("test.tiger", DISPATCH_QUEUE_SERIAL);
        [self performSelector:@selector(ontimeFunc) withObject:nil afterDelay:5];
    }
    return self;
}

调用的函数如下:

- (void)ontimeFunc
{
    dispatch_async(self.queue, ^{
        [self test];
    });
}

- (void)test
{
    NSLog(@"%@ called",NSStringFromClass([self class]));
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    //当前是非主线程。5s后,线程已经消失了,就不会被调用了。不能这么用
    [self performSelector:@selector(ontimeFunc) withObject:nil afterDelay:5];        
}

原本需要实现的目标是每 5s 调用 test函数一次。但是因为 performSelector:withObject:afterDelay:是在后台线程调用的,这个线程没有 RunLoop,所以 5s 后,线程已经不存在了,因此 test 方法一次都不会被调用。

这里需要修改的地方有两个:

  1. init 方法中,dispatch到主线程执行 performSelector 方法。
  2. test 方法中,也需要dispatch到主线程执行 performSelector 方法。

其实不一定需要到主线程中,只需要 5s 后,线程存在即可。

NSTimer 没有被触发

Timers work in conjunction with run loops

Apple 的文档中,第一句话就是定时器和 RunLoop 是联合工作的。定时器必须被加到 RunLoop 中才能被执行。
创建定时器有两种方法:

  • scheduledTimerWithTimeInterval:repeats:block:
    创建一个定时器,并加到当前 RunLoop 的 default mode 中。
  • timerWithTimeInterval:repeats:block:
    只是创建一个定时器,需要手动加到 RunLoop 中。

因此如果使用第二种方法,对应的代码不会被延迟执行。
此外,如果在后台队列中创建定时器,可以 dispatch 到主线程中创建,因为后台队列对应的线程很可能会马上消失。
如果把定时器加入的 mode A,指定时间后,当前 RunLoop 处于 mode B,那么也不会被执行。比如把定时器加到 default mode 下,当 scrollview 滚动时,会处于 UITrackingMode,不会被触发。
关于 RunLoop 的知识,可以参考苹果文档及底部链接。

参考

转载于:https://www.cnblogs.com/huahuahu/p/NSTimerperformSelector-han-shu-mei-you-bei-diao-yo.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值