runLoop 添加timer的正确方式 (ios oc)

关于runloop的知识请自行补脑。

当项目中需要启动计时器进行计数的时候,往往直接添加到主线程上(默认方式,刷新ui方便),但是会导致诸如:tableview滑动事件、ui操作、app后台切换的时候影响计时的准确性设置导致计时器停止,先来看一般的添加方式:

方式:主线程(NSDefaultRunLoopModes):

[NSThread detachNewThreadSelector:@selector(startTimer) toTarget:self withObject:nil];//此方式虽然在子线程,但是不推荐(ui刷新有问题和nsrunloopmodes的依赖,导致该方法不彻底)
本质和下面直接写类似:

[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timerFire) userInfo:nil repeats:YES];

- (void)startTimer
{
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timerFire) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop]run];
}

- (void)timerFire
{
    self.intervalTimespan -= 1;
    [self performSelectorOnMainThread:@selector(updateSendRequestBtnTitle) withObject:nil waitUntilDone:YES];
    if (0 >= self.intervalTimespan) {
        [self.timer invalidate];
        return;
    }
}

正确姿势一:修改 NSRunLoopCommonModes,然后用addTimer方式:

if(self.timer){
[self.timer invalidate];
self.timer = nil;
}
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timerFire) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];

正确姿势二:子线程

 NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(startTimer) object:nil];
  [thread start];

- (void)startTimer
{
    
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timerFire) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop]run];

}
刷新:
- (void)timerFire
{
    self.intervalTimespan -= 1;
    dispatch_async(dispatch_get_main_queue(), ^{
        [self updateSendRequestBtnTitle];
    });
    if (0 >= self.intervalTimespan) {
        [self.timer invalidate];
        return;
    }
}

正确姿势三:GCD

<pre name="code" class="objc">   uint64_t interval = 0.01 * NSEC_PER_SEC;
    dispatch_queue_t queue = dispatch_queue_create("timer queue", 0);
    
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, interval,  0);
    __weak UIViewController *weakSelf = self;
    dispatch_source_set_event_handler(timer, ^{
        NSLog(@"Timer:%@",[NSThread currentThread]);
        [weakSelf  timerFire];
    });
    dispatch_resume(timer);


 刷新: 
timerFire中: 

    dispatch_async(dispatch_get_main_queue(), ^{
        self.label.text = @"something";
    })





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值