定时器 NSTimer

综述

NSTimer的初始化有很多种

  • 初始化函数:
self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0
                                              target:self
                                            selector:@selector(Typing)
                                            userInfo:nil
                                             repeats:YES];
  • 含义:
    定时器启动后,每隔2s中回调一次 @selector
  • 参数
    • scheduledTimerWithTimeInterval :定时时间
    • target:目标,通常设为self
    • selector:回调函数,不用解释了
    • userInfo:总是设为nil
    • repeats:是否重复
  • 下面通过代码来说明初始化之后
    • 启动定时器
    • 终止定时器
    • 释放定时器
#import "ViewController.h"
@interface ViewController ()
@property (strong,nonatomic) NSTimer *timer;
@property (nonatomic) NSUInteger count;
@property (weak, nonatomic) IBOutlet UILabel *label;
@end
// -------- 实现 -----------
@implementation ViewController
-(void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        self.count = 0;
}
-(IBAction)start:(UIButton *)sender {
        if (!self.timer) {
            self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0
                                                          target:self
                                                        selector:@selector(Typing)
                                                        userInfo:nil
                                                         repeats:YES];
        }
        NSLog(@"%@",self.timer);
        [self.timer fire];
}
-(IBAction)stop:(UIButton *)sender {
        NSLog(@"<><><><><<><><>>>>>>>>>>>>>>>>>>>>>>>\n%@",self.timer);
        [self.timer invalidate];
    //    self.timer = nil;
        NSLog(@"<><><><><<><><>>>>>>>>>>>>>>>>>>>>>>>\n%@",self.timer);
}
-(void)Typing{
        self.count ++;
        self.label.text = [NSString stringWithFormat:@"fuck %lu",self.count];
}
-(void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end

定时器和Runloop —— 待完善

启动定时器除了使用 [self.timer fire]外也可以用Runloop来做。不过具体含义还不清楚

self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
                                                  target:self
                                                selector:@selector(typing)
                                                userInfo:nil
                                                 repeats:YES];
    //    [self.timer fire];
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0]];

先说初始化和启动定时器

  • 初始化定时器
    • 必须先判断定时器是否存在。否则会同时创建N个定时器

2016-01-23 11:09:37.283 TestForTimer[7792:548179] <__NSCFTimer: 0x7f84e9c09920>
2016-01-23 11:09:37.626 TestForTimer[7792:548179] <__NSCFTimer: 0x7f84e9e185f0>
2016-01-23 11:09:37.837 TestForTimer[7792:548179] <__NSCFTimer: 0x7f84e9eb89b0>

2016-01-23 11:09:38.004 TestForTimer[7792:548179] <__NSCFTimer: 0x7f84e9d0ae90>
2016-01-23 11:09:38.187 TestForTimer[7792:548179] <__NSCFTimer: 0x7f84e9c0d500>
2016-01-23 11:09:38.338 TestForTimer[7792:548179] <__NSCFTimer: 0x7f84e9e1da70>

  • 这样做的后果是,使用[self.timer invalidate];的时候,只会终止创建的第一个_NSCFTimer: 0x7f84e9c09920>,剩下的定时器仍然在跑,无法终止。
  • 开启定时器 [self.timer fire]; 最好把这个和初始化定时器放在一起。
    上面的代码中,如果我一直点击[self.timer fire],定时器不会被新建,但是会从我点击之下开始,重新计时!!
  • 终止定时器
    • 调用[self.timer invalidate]; 之后务必将其释放,赋值为nil,这样下次通过事件按钮触发的时候才能创建一个新的定时器

综上,定时器的创建和销毁必须是一对一的!

  • 创建时,必须判断定时器是否存在!
  • 触发时,定时器会重新计时,但是不影响对象的创建和销毁
  • 终止定时器,必须将先前创建的定时器销毁!= nil 操作,很重要!

疑问

当 NSTimer 和 NSCondition 一起使用的时候,似乎无法在NSCondition中阻塞线程后去调用定时器,这样做的后果是定时器的回调函数,只执行一次后就停止了。尚不清楚原因
尝试过用GCD另开线程来做NSTimer,也并不管用。


2017.05.05更新

iOS 10后新增了一种快速定义定时器的类方法:

//API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block

说明:(感觉这个函数会更方便一些)

和上面传统的描述不同的是,这个类方法,在NSTimer实例化后,并不需要手动去fire.就像函数说明中写的

After interval seconds have elapsed, the timer fires, executing block.

  • 只要时间到了,就会去执行block中的内容。
  • 另外要注意的是,block中的参数 timer就是我们定义的这个timer本身。相当于说在block回调中返回这个定义的实例化变量。
self.reconnectTimer = [NSTimer scheduledTimerWithTimeInterval:self.spaceTime repeats:YES block:^(NSTimer * _Nonnull timer) {
// timer和self.reconnectTimer 其实是一回事
}];

下面是代码块示例:

__block NSUInteger count = 0;
self.reconnectTimer = [NSTimer scheduledTimerWithTimeInterval:self.spaceTime repeats:YES block:^(NSTimer * _Nonnull timer) {
    if (count > self.reconnectTimes || self.isConneted == YES) {
        NSLog(@"计数终止");
        count = 0;
        [timer invalidate];
    } else {
        NSLog(@"计数值 = %lu",count);
        count += 1;
        [self.centralManager connectPeripheral:peripheral options:nil];
    }
}];

你可能感兴趣的:(定时器 NSTimer)