抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

使用NSTimer最好是升级为属性,容易控制

简单使用

  • 设置为属性

    @property (nonatomic ,strong) NSTimer *timer; //定时器

  • 懒加载
    1
    2
    3
    4
    5
    6
    -(NSTimer*)timer{
    if (_timer == nil) {
    _timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateUI) userInfo:nil repeats:YES];
    }
    return _timer;
    }
  • 开始动画与暂停动画
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /**
    * 开始动画
    */
    -(void)beginAnimation{
    self.timer.fireDate=[NSDate distantPast];
    }
    /**
    * 结束动画
    */
    -(void)endAnimation{
    self.timer.fireDate=[NSDate distantFuture];
    }

如果只是使用的话,这已经完了,但是会造成self无法释放

==================================


解决办法,在界面要不显示的时候把定时器注销并且置空

1
2
3
4
5
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[self.timer invalidate];
self.timer = nil;
}

这样就可以了,可以打印dealloc测试了

GCD

dispatch source是一个监视某些类型事件的对象。当这些事件发生时,它自动将一个block放入一个dispatch queue的执行例程中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
  *  创建dispatch源
  *
 *  @param DISPATCH_SOURCE_TYPE_TIMER 事件源的类型
  *  @param 0                          <#0 description#>
  *  @param 0                          <#0 description#>
  *  @param dispatch_get_main_queue    在哪个线程上执行
  *
 *  @return dispatch_source_t
 */
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
/**
  * @param start 控制计时器第一次触发的时刻
  * @param interval 每隔多长时间执行一次
  * @param leeway 误差值,0表示最小误差,值越小性能消耗越大
  */
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
/**
 *  事件处理的回调
  */
dispatch_source_set_event_handler(timer, ^{
    //取消定时器
  dispatch_cancel(timer);
});
/**
  *  Dispatch source启动时默认状态是挂起的,我们创建完毕之后得主动恢复,否则事件不会被传递,也不会被执行
 */
dispatch_resume(timer);
GCD定时器的优点有很多,首先不受Mode的影响,而NSTimer受Mode影响时常不能正常工作,除此之外GCD的精确度明显高于NSTimer,这些优点让我们有必要了解GCD定时器这种方法。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
-(void)clickOnButton
{    
    //获取一个并行队列 (默认优先级队列)
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //创建 timer
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    _timer = timer;
    //设置timer间隔和精度
    //interval:间隔 (纳秒),配合NSEC_PER_SEC用就是秒
    //leeway:精度 ,最高精度当然就传0。
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);
    //设置回调
    WeakObj(self);
    __block NSInteger count = 0;
    dispatch_source_set_event_handler(timer, ^{
        NSString *str = nil;
        if (count >= 3600) {
            str = [NSString stringWithFormat:@"%02d:%02d:%02d",(int)(count/3600),(int)((count%3600)/60),(int)(count%60)];
        }else{
            str = [NSString stringWithFormat:@"%02d:%02d",(int)(count/60),(int)(count%60)];
        }
        
        MAIN(^{
            selfWeak.timeLabel.text = str;
        });
        count++;
    });
    dispatch_resume(timer);
}