iOS进阶-谈谈定时器

目录

  1. iOS提供定时器API
  2. 定时器开发中的坑

一、 iOS提供定时器API

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;

二、定时器开发中的坑

2.1、必须***又一个runloop

系统框架提供了几种创建NSTimer的方法,其中以scheduled开头的方***自动把timer加入当前RunLoop,到了设定时间就会触发selector方法,而没有scheduled开头的方法则需要手动添加timer到一个RunLoop中才会有效。
程序启动时,会默认启动主线程的RunLoop并在程序运行期内有效,所以把timer放入主线程时不需要启动RunLoop,但现实开发中主线程更多的是处理UI事物,把耗时且耗能的操作放在子线程中,这就需要将子线程的RunLoop激活。
注意: 由于RunLoop自己主要有两种使用模式:NSDefaultRunLoopMode、NSEventTrackingRunLoopMode,一般会默认使用NSDefaultRunLoopMode,但是默认模式会出现当界面UI如果存在连续事件,定时器会自动进入NSEventTrackingRunLoopMode模式定时器将会被停止。一般我们都是用NSRunLoopCommonModes,它是前两者的集合;

2.2、内存泄漏

- (void)cancel{
      [_timer invalidate];
      _timer = nil;
}
- (void)dealloc{
      [self cancel];
}

我们通常会在界面销毁的生命周期函数销毁,但是是没有效果的:我们分析下:

当我们当前一个定时器_timer,_timer对target、userInfo,存在一个强引用,target、userInfo的引用技术都会加一,一般target都是当前类的对象,那么因为_time一直对当前类有一个强的引用,导致它无法销毁,导致内存泄漏,所以以上的释放方式是不对的。

正确的方式如下:应该在界面消失的时候释放:

- (void)viewWillDisappear:(BOOL)animated{
       [super viewWillDisappear:animated];
       [self cancel];
}

注意: 释放Time,执行 invalidate 需要在统一线程使用,不允许跨线程。

全部评论

相关推荐

oppo 应用软开 22*15+0.5*12
拿到了ssp完美:真的坎坷,但是你至少拿到这么多offer了!
点赞 评论 收藏
分享
感性的干饭人在线蹲牛友:🐮 应该是在嘉定这边叭,禾赛大楼挺好看的
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务