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