服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - iOS中的NSTimer定时器的初步使用解析

iOS中的NSTimer定时器的初步使用解析

2021-01-18 13:26李刚 IOS

这篇文章主要介绍了iOS中的NSTimer定时器的初步使用解析,通过例子简单讲解了NSTimer的输出与停止的方法,需要的朋友可以参考下

创建一个定时器(nstimer)

?
1
2
3
4
5
6
7
8
9
- (void)viewdidload {
  [super viewdidload];
  [nstimer scheduledtimerwithtimeinterval:1 target:self selector:@selector(actiontimer:) userinfo:nil repeats:yes];
}
 
- (void)actiontimer:(nstimer *)timer
{
 
}

nstimer默认运行在default mode下,default mode几乎包括所有输入源(除nsconnection) nsdefaultrunloopmode模式。

actiontimer方法会每隔1s中被调用一次。nstimer使用起来是不是非常简单。这是nstimer比较初级的应用。

当主界面被滑动时nstimer失效了

主界面被滑动是什么意思呢?就是说主界面有uitableview或者uiscrollview,滑动uitableview或者uiscrollview。这个时候nstimer失效了。

我们来写一个demo,在一个有uitableview的uiviewcontroller上启动定时器,每1s数字加1,并将这个数字显示在uilabel上面.

?
1
2
3
4
5
6
7
8
9
10
11
- (void)viewdidload {
  [super viewdidload];
  [nstimer scheduledtimerwithtimeinterval:1 target:self selector:@selector(actiontimer:) userinfo:nil repeats:yes];
}
 
- (void)actiontimer:(nstimer *)timer
{
  self.number++;
  self.label.text = [nsstring stringwithformat:@"%d",self.number];
  nslog(@"%d",self.number);
}

关于uitableview和uilabel的创建我省去了。详细的代码可以点击这里下载:iosstrongdemo,iosstrongdemo我会不断更新,大家在github上star一下。

这样当用户在拖动uitableview处于uitrackingrunloopmode时,nstimer就失效了,不能fire。self.label上的数字也就无法更新。

iOS中的NSTimer定时器的初步使用解析

修改nstimer的run loop

解决方法就是将其加入到uitrackingrunloopmode模式或nsrunloopcommonmodes模式中。

?
1
[[nsrunloop currentrunloop] addtimer:timer formode:uitrackingrunloopmode];

或者

?
1
[[nsrunloop currentrunloop] addtimer:timer formode:nsrunloopcommonmodes];

nsrunloopcommonmodes:是一个模式集合,当绑定一个事件源到这个模式集合的时候就相当于绑定到了集合内的每一个模式。

iOS中的NSTimer定时器的初步使用解析

 

fire

我们先用 nstimer 来做个简单的计时器,每隔5秒钟在控制台输出 fire 。比较想当然的做法是这样的:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@interface detailviewcontroller ()
@property (nonatomic, weak) nstimer *timer;
@end
 
@implementation detailviewcontroller
- (ibaction)firebuttonpressed:(id)sender {
  _timer = [nstimer scheduledtimerwithtimeinterval:3.0f
                       target:self
                      selector:@selector(timerfire:)
                      userinfo:nil
                       repeats:yes];
  [_timer fire];
}
 
-(void)timerfire:(id)userinfo {
  nslog(@"fire");
}
@end

运行之后确实在控制台每隔3秒钟输出一次 fire ,然而当我们从这个界面跳转到其他界面的时候却发现:控制台还在源源不断的输出着 fire 。看来 timer 并没有停止。

invalidate

既然没有停止,那我们在 demoviewcontroller 的 dealloc 里加上 invalidate 的方法:

?
1
2
3
4
-(void)dealloc {
  [_timer invalidate];
  nslog(@"%@ dealloc", nsstringfromclass([self class]));
}

再次运行,还是没有停止。原因是 timer 添加到 runloop 的时候,会被 runloop 强引用:

note in particular that run loops maintain strong references to their timers, so you don't have to maintain your own strong reference to a timer after you have added it to a run loop.
然后 timer 又会有一个对 target 的强引用(也就是 self ):

target is the object to which to send the message specified by aselector when the timer fires. the timer maintains a strong reference to target until it (the timer) is invalidated.
也就是说 nstimer 强引用了 self ,导致 self 一直不能被释放掉,所以也就走不到 self 的 dealloc 里。

既然如此,那我们可以再加个 invalidate 按钮:

?
1
2
3
- (ibaction)invalidatebuttonpressed:(id)sender {
  [_timer invalidate];
}

嗯这样就可以了。(在 sof 上有人说该在 invalidate 之后执行 _timer = nil ,未能理解为什么,如果你知道原因可以告诉我:)

在 invalidate 方法的文档里还有这这样一段话:

you must send this message from the thread on which the timer was installed. if you send this message from another thread, the input source associated with the timer may not be removed from its run loop, which could prevent the thread from exiting properly.
nstimer 在哪个线程创建就要在哪个线程停止,否则会导致资源不能被正确的释放。看起来各种坑还不少。

dealloc

那么问题来了:如果我就是想让这个 nstimer 一直输出,直到 demoviewcontroller 销毁了才停止,我该如何让它停止呢?

  • nstimer 被 runloop 强引用了,如果要释放就要调用 invalidate 方法。
  • 但是我想在 demoviewcontroller 的 dealloc 里调用 invalidate 方法,但是 self 被 nstimer 强引用了。
  • 所以我还是要释放 nstimer 先,然而不调用 invalidate 方法就不能释放它。
  • 然而你不进入到 dealloc 方法里我又不能调用 invalidate 方法。
  • 嗯…

延伸 · 阅读

精彩推荐
  • IOSiOS10 Xcode8适配7个常见问题汇总

    iOS10 Xcode8适配7个常见问题汇总

    这篇文章主要为大家详细汇总了iOS10 Xcode8适配7个常见问题,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    索马里猫10332021-02-01
  • IOSiOS常见的几个修饰词深入讲解

    iOS常见的几个修饰词深入讲解

    这篇文章主要给大家介绍了关于iOS常见的几个修饰词的相关资料,iOS修饰词包括assign、weak、strong、retain、copy、nonatomic、atomic、readonly、readwrite,文中通过示...

    郡王丶千夜7422021-05-10
  • IOS谈一谈iOS单例模式

    谈一谈iOS单例模式

    这篇文章主要和大家谈一谈iOS中的单例模式,单例模式是一种常用的软件设计模式,想要深入了解iOS单例模式的朋友可以参考一下...

    彭盛凇11872021-01-19
  • IOSIOS网络请求之AFNetWorking 3.x 使用详情

    IOS网络请求之AFNetWorking 3.x 使用详情

    本篇文章主要介绍了IOS网络请求之AFNetWorking 3.x 使用详情,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    总李写代码6892021-03-04
  • IOSiOS APP实现微信H5支付示例总结

    iOS APP实现微信H5支付示例总结

    这篇文章主要介绍了iOS APP实现微信H5支付示例总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下...

    一张小A11332021-06-01
  • IOSxcode8提交ipa失败无法构建版本问题的解决方案

    xcode8提交ipa失败无法构建版本问题的解决方案

    xcode升级到xcode8后发现构建不了新的版本。怎么解决呢?下面小编给大家带来了xcode8提交ipa失败无法构建版本问题的解决方案,非常不错,一起看看吧...

    Cinna丶7542021-02-03
  • IOSiOS中时间与时间戳的相互转化实例代码

    iOS中时间与时间戳的相互转化实例代码

    这篇文章主要介绍了iOS中时间与时间戳的相互转化实例代码,非常具有实用价值,需要的朋友可以参考下。...

    张无忌!4812021-03-09
  • IOSiOS逆向教程之logify跟踪方法的调用

    iOS逆向教程之logify跟踪方法的调用

    这篇文章主要给大家介绍了关于iOS逆向教程之logify跟踪方法调用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学...

    Mr.Guo11472021-04-28