天天看点

NSTimer的使用

Demo实例

NSTimer计时器,主要用于进行定时执行指定方法,常用场景如:获取验证码的按钮倒计时。

使用步骤:

1、实例化

1-1、倒计时时间间隔(时间单位:秒)

1-2、指定的执行方法

1-3、实现指定执行方法的对象

1-4、是否重复执行

2、对象的内存管理及销毁

2-1、使用方法" invalidate "进行停止

2-2、将对象设置为" nil "

2-3、特别是在返回到其他视图控制器的时候,要在方法" - (void)viewWillDisappear:(BOOL)animated "中(注意:不能在方法" - (void)dealloc "在设置)将timer停止,并置为nil,如:

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    
    // 有效销毁
    if (self.timer && [self.timer isValid])
    {
        [self.timer invalidate];
        self.timer = nil;
        NSLog(@"3 停止");
    }
}
           
- (void)dealloc
{
    NSLog(@"%@ 已经销毁", [self class]);
    
    // 无效销毁
    if (self.timer && [self.timer isValid])
    {
        [self.timer invalidate];
        self.timer = nil;
        NSLog(@"3 停止");
    }
}
           
// 实例化方法1 初始化后即开始执行
if (self.timer == nil)
{
    self.time = 10.0;
    // 带参数
    NSNumber *number = @(self.time);
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(countDownTime:) userInfo:number repeats:YES];
    // 非必要设置,实际已设置为 NSDefaultRunLoopMode 模式
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}

- (void)countDownTime:(NSTimer *)timer
{
    NSLog(@"timer valueclass = %@, value = %@", [timer.userInfo class], timer.userInfo);

    self.time -= 1; // 等价于:self.time = self.time - 1;
    
    if (0 > self.time)
    {
        // 关闭定时器方法1
        [self.timer invalidate];
        self.timer = nil;
    }
}
           
// 实例化方法2 初始化后,需要调用" setFireDate "才开始执行
if (self.timer == nil)
{
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(countDownTime:) userInfo:nil repeats:YES];
    // 非必要设置,实际已设置为 NSDefaultRunLoopMode 模式
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
    [self.timer setFireDate:[NSDate distantFuture]];
}
self.time = 10.0;
[self.timer setFireDate:[NSDate distantPast]];
    
- (void)countDownTime:(NSTimer *)timer
{
    NSLog(@"timer valueclass = %@, value = %@", [timer.userInfo class], timer.userInfo);

    self.time -= 1; // 等价于:self.time = self.time - 1;
    NSLog(@"倒计时 time = %@", @(self.time));
    
    if (0 > self.time)
    {        
        // 关闭定时器方法2
	[self.timer setFireDate:[NSDate distantFuture]];
    }
}
           
// 实例化方法3 初始化后,需要调用" fire "才开始执行
if (self.timer == nil)
{
    self.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(countDownTime:) userInfo:nil repeats:YES];
    // 必须设置 NSRunLoop 线程池,否则无效
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}
self.time = 10.0;
[self.timer fire];

- (void)countDownTime:(NSTimer *)timer
{
    NSLog(@"timer valueclass = %@, value = %@", [timer.userInfo class], timer.userInfo);

    self.time -= 1; // 等价于:self.time = self.time - 1;

    NSLog(@"倒计时 time = %@", @(self.time));
    
    if (0 > self.time)
    {        
        // 关闭定时器方法3
	[self.timer invalidate];
    }
}
           
NSTimer的使用
NSTimer的使用
NSTimer的使用
NSTimer的使用

NSTimer在使用过程中的注意事项: 1、NSTimer在使用时,拥有timer的对象,会被自动retain引用,特别是重复执行的timer。这时候就会造成该对象永远不会被释放,即内存泄露,且timer也一直在运行。要解决这个问题,必须调用NSTimer的invalidate属性。 2、NSTimer在使用过程中会受到多线程的限制,因为NSTimer被实例化后,会被主动加到主线程默认的runloop中的default mode中,即使添加到程序员自己指定的runloop的其他模式中,也同样会受影响。这时候,造成的影响是timer没有有效的按设置的时间重复执行指定的方法。要解决这个问题,必须区分不同的runloop模式,且runloop都必须启动。

继续阅读