NSTimer

创建

// 创建一个定时器,但是么有添加到运行循环,我们需要在创建定时器后手动的调用 NSRunLoop 对象的 addTimer:forMode: 方法。
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo; 


// 创建一个timer并把它指定到一个默认的runloop模式中,并且在 TimeInterval时间后 启动定时器 
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo; 


// 创建一个定时器,但是么有添加到运行循环,我们需要在创建定时器后手动的调用 NSRunLoop 对象的 addTimer:forMode: 方法。 
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo; 


// 创建一个timer并把它指定到一个默认的runloop模式中,并且在 TimeInterval时间后 启动定时器 
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo; 


// 默认的初始化方法,(创建定时器后,手动添加到 运行循环,并且手动触发才会启动定时器)
- (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(nullable id)ui repeats:(BOOL)rep NS_DESIGNATED_INITIALIZER; 


开启

// 启动 Timer 触发Target的方法调用但是并不会改变Timer的时间设置。 即 time没有到达到,Timer会立即启动调用方法且没有改变时间设置,当时间 time 到了的时候,Timer还是会调用方法。
- (void)fire;

// 设置定时器的启动时间,常用来管理定时器的启动与停止 
@property (copy) NSDate *fireDate; 

timer.fireDate = [NSDate distantPast];  // 开启定时器
timer.fireDate = [NSDate distantFuture]; // 停止定时器
[timer setFireDate:[NSDate date]]; // 继续定时器

停止

// 获取定时器是否有效
@property (readonly, getter=isValid) BOOL valid;

// 停止 Timer,即将定时器设置成无效 ---> 将定时器从循环池中移除
- (void)invalidate;

其他属性

// 这个是一个只读属性,获取定时器调用间隔时间
@property (readonly) NSTimeInterval timeInterval;
// 这是7.0之后新增的一个属性,因为NSTimer并不完全精准,通过这个值设置误差范围
@property NSTimeInterval tolerance NS_AVAILABLE(10_9, 7_0);

注意

  • 参数repeats是指定是否循环执行,YES将循环,NO将只执行一次。

  • timerWithTimeInterval这两个类方法创建出来的对象如果不用 addTimer: forMode方法手动加入主循环池中,将不会循环执行。

  • scheduledTimerWithTimeInterval 这两个方法会将定时器添加到当前的运行循环,运行循环的模式为默认模式。如果需要第一次就执行一次,需要调用开启定时器的方法。

  • init方法需要手动加入循环池,它会在设定的启动时间启动。

  • 在页面释放前先释放定时器。

  • CFRunLoopAddTimer EXC_BAD_ACCESS
    在使用timer时候没注意申明成了weak类型的,结果运行后程序出现CFRunLoopAddTimer EXC_BAD_ACCESS的闪退。原因是timer对象可能被释放掉了,又往mainRunLoop里添加timer,就闪退了。


内存释放问题

  • 如果我们启动了一个定时器,在某个界面释放前,将这个定时器停止,甚至置为nil,都不能使这个界面释放,原因是系统的循环池中还保有这个对象。

NSTimer为什么要添加到RunLoop中才会有作用

1、NSTimer其实也是一种资源(事件),我们会发现所有的source(事件)如果要起作用,就得加到runloop中,而且此runloop应该是有效的,执行着的。
2、同理timer这种资源要想起作用,那肯定也需要加到runloop中才会有效。
3、如果一个runloop里面不包含任何资源(事件)的话,运行该runloop时会处于一种休眠状态等待下一个事件。所以如果创建了timer但是不添加runloop的话,timer资源处于一种闲置等待状态。


Code

- (void)startLiveTimer {
    [self stopLiveTimer];
    self.timerClock = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerEvent) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:self.timerClock forMode:NSDefaultRunLoopMode];
    self.timerClock.fireDate = [NSDate distantPast];
}
- (void)stopLiveTimer {
    if (self.timerClock) {
        self.timerClock.fireDate = [NSDate distantFuture];
        [self.timerClock invalidate];
        self.timerClock = nil;
    }
}
- (void)timerEvent {

}

如果有列表滑动页面什么的,可以将timer添加在runloop的NSRunLoopCommonModes的mode下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
引用\[1\]: \[runLoop addTimer:myTimer forMode:NSDefaultRunLoopMode\]; //实际上这步是不需要,scheduledTimerWithTimeInterval已经纳入当前线程运行。如果使用timerWithTimeInterval则需要。 引用\[2\]: \[\[NSRunLoop currentRunLoop\] addTimer:_timer forMode:NSDefaultRunLoopMode\]; //_timer = \[NSTimer scheduledTimerWithTimeInterval:1.f target:self selector:@selector(timerAction) userInfo:nil repeats:YES\]; 引用\[3\]: GCD的定时器不受RunLoop中Mode的影响(RunLoop内部也是基于GCD实现的,可以根据源码看到), 比如滚动TableView的时候,GCD的定时器不受影响;且比NSTimer更加准时。 问题: NSTimer的mode是什么意思? 回答: NSTimer的mode是指定定时器在运行时所处的运行循环模式。在使用NSTimer时,可以通过指定mode来控制定时器在哪些运行循环模式下运行。比如在引用\[1\]和引用\[2\]中,都使用了NSDefaultRunLoopMode作为定时器的运行循环模式。这意味着定时器会在默认的运行循环模式下运行。而GCD的定时器则不受RunLoop中Mode的影响,可以在任何运行循环模式下运行,如引用\[3\]所示。 #### 引用[.reference_title] - *1* [iOS多线程的初步研究(四)-- NSTimer](https://blog.csdn.net/lengshengren/article/details/12905635)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [NSTimer 基本使用和注意事项](https://blog.csdn.net/wutengwei007/article/details/82221069)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Morris_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值