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

示例:
NSTimer *timer = = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerAction:) userInfo:nil repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

// 创建一个timer并把它指定到一个默认的runloop模式中,并且在 TimeInterval时间后 启动定时器
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
示例:
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction:) userInfo:nil repeats:NO];
// 默认的初始化方法,(创建定时器后,手动添加到 运行循环,并且手动触发才会启动定时器)
- (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(nullable id)ui repeats:(BOOL)rep NS_DESIGNATED_INITIALIZER
示例:
NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:1] interval:1 target:self selector:@selector(timerAction:) userInfo:nil repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
二、NSTImer使用
// 启动 Timer 触发Target的方法调用但是并不会改变Timer的时间设置。 即 time没有到达到,Timer会立即启动调用方法且没有改变时间设置,当时间 time 到了的时候,Timer还是会调用方法。 - (void)fire;
// 启动定时器
timer.fireDate = [NSDate distantPast];
//停止定时器
timer.fireDate = [NSDate distantFuture];
// 开启
[time setFireDate:[NSDate distanPast]]
//关闭
[time setFireDate:[NSDate distantFunture]]
//继续。
[timer setFireDate:[NSDate date]];
// 停止 Timer ---> 唯一的方法将定时器从循环池中移除 - (void)invalidate;
三、NSTimer注意事项
3.1、NSTimer加到了RunLoop中但未能触发事件
原因主要有以下两个:
3.1.1、runloop是否运行
每一个线程都有它自己的runloop,程序的主线程会自动的使runloop生效,但对于我们自己新建的线程,它的runloop是不会自己运行起来,当我们需要使用它的runloop时,就得自己启动。
- (void)applicationDidBecomeActive:(UIApplication *)application {
  // NSThread 创建一个子线程
  [NSThread detachNewThreadSelector:@selector(testTimerSheduleToRunloop1) toTarget:self withObject:nil];
}
// 测试把timer加到不运行的runloop上的情况
- (void)testTimerSheduleToRunloop1 {
  NSLog(@"Test timer shedult to a non-running runloop");
  NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:1] interval:1 target:self selector:@selector(timerAction:) userInfo:nil repeats:NO];
  [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; // 打开下面一行输出runloop的内容就可以看出,timer却是已经被添加进去
  //NSLog(@"the thread's runloop: %@", [NSRunLoop currentRunLoop]);
  // 打开下面一行, 该线程的runloop就会运行起来,timer才会起作用
  [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];
}
- (void)applicationWillResignActive:(UIApplication *)application {
  NSLog(@"SvTimerSample Will resign Avtive!");
}
3.1.2、mode是否正确
run loop在运行时一般有两个mode,一个defaultmode,一个trackingmode。同一线程的runloop在运行的时候,任意时刻只能处于一种mode。所以只能当程序处于这种mode的时候,timer才能得到触发事件的机会。
正常情况下run loop使用defaultmode,scheduled生成的timer会默认添加到defaultmode中,当我们互动scrollview时,run loop切换到trackingmode运行,于是我们发现定时器失效了。为了使定时器在我们滑动scrollview时也能正常运行,我们需要确保defaultmode和trackingmode里都添加了我们生成的timer。如:
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:_timeInterval target:self selector:@selector(addone) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
或者:
NSTimer *timer = [NSTimer timerWithTimeInterval:_timeInterval target:self selector:@selector(addone) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
或者
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:_timeInterval target:self selector:@selector(addone) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
综上: 要让timer生效,必须保证该线程的runloop已启动,而且其运行的runloopmode也要匹配。
3.2、NSTimer的释放
使用NSTimer时,timer会保持对target和userInfo参数的强引用。只有当调取了NSTimer的invalidate方法时,NSTimer才会释放target和userInfo。
生成timer的方法中如果repeats参数为NO,则定时器触发后会自动调取invalidate方法。如果repeats参数为YES,则需要程序员手动调取invalidate方法才能释放timer对target和userIfo的强引用。
在使用repeats参数为YES的定时器时,如果在使用完定时器时后没有调取invalidate方法,导致target和userInfo没有被释放,则可能会形成循环引用情况,从而影响内存释放。
//取消定时器
[timer invalidate]; // 将定时器从运行循环中移除
timer = nil; // 销毁定时器 ---》 这样可以避免控制器不死

转载于:https://www.cnblogs.com/huaixu/p/7242599.html

【整理】NSTimer使用及注意事项相关推荐

  1. php 芝麻认证think_PHP 芝麻信用接入的注意事项

    芝麻官方下载的SDK,跑不起来,百度搜索一番也没有发现太多的文章 ,只有一个CSDN博客写的一篇文章,比较有参考价值 详细查阅文档+几天测试整理以下几点注意事项: 接入芝麻API接口,应该分2步: 第 ...

  2. 2023年高新技术企业认定申报注意事项

    据统计,全国有效期内高新技术企业33万家.为了帮助企业提前准备和更好地开展2023年高新技术企业认定申报工作,深科信小编整理了一份注意事项和现在可做的工作,快来看看吧! 重点关注 (一)研发费用归集& ...

  3. 应聘需要注意事项(反问面试官)

    常州姜东整理(应聘需要注意事项),一直以来都是面试官(企业)为大,应聘者往往都是弱势群体,面试完了就是一句回去等消息,很多应聘者来面试过程中不知道问什么或者问不清一些公司情况,导致入职后出现信息不对称 ...

  4. 手术室无菌注意事项的内容

    劳动节很快就要到了,很多网友问小编有关手术室无菌注意事项的内容?最新手术室无菌注意事项有哪些?下面小编整理了手术室无菌注意事项的技术, 让我们来详细的了解一下手术室无菌注意事项有哪些, 1.手术室无菌 ...

  5. 外贸独立站运营注意事项

    很多做跨境电商的外贸人不希望被各种国际电商平台的规则所限制(例如阿里巴巴.亚马逊等.),但是想转独立站的模式经营外贸.近年来,外贸人创建自己的独立贸易站在外贸圈越来越流行.独立站之所以受到很多外贸&q ...

  6. php 芝麻信用授权页面,PHP 芝麻信用接入的注意事项

    本文给大家整理了接入芝麻api借口的两点注意事项,对php 芝麻信用接入感兴趣的朋友通过本文一起学习吧 芝麻官方下载的SDK,跑不起来,百度搜索一番也没有发现太多的文章 ,只有一个CSDN博客写的一篇 ...

  7. 芝麻信用网页api php,PHP芝麻信用接入的注意事项

    本文给大家整理了接入芝麻api借口的两点注意事项,对php 芝麻信用接入感兴趣的朋友通过本文一起学习吧 芝麻官方下载的SDK,跑不起来,百度搜索一番也没有发现太多的文章 ,只有一个CSDN博客写的一篇 ...

  8. 芝麻信用网页api php,PHP芝麻信用接入的注意事项_php实例

    芝麻官方下载的SDK,跑不起来,百度搜索一番也没有发现太多的文章 ,只有一个CSDN博客写的一篇文章,比较有参考价值 详细查阅文档+几天测试整理以下几点注意事项: 接入芝麻API接口,应该分2步: 第 ...

  9. php获取芝麻分,PHP编程:PHP 芝麻信用接入的注意事项

    <PHP编程:PHP 芝麻信用接入的注意事项>要点: 本文介绍了PHP编程:PHP 芝麻信用接入的注意事项,希望对您有用.如果有疑问,可以联系我们. PHP实例详细查阅文档+几天测试整理以 ...

最新文章

  1. linux系统下如何github,Linux系统下如何安装和使用GitHub
  2. 织梦html仅动态,dede织梦系统后台发布文章时设置为默认动态浏览的方法
  3. 洛谷 P2015 二叉苹果树
  4. BRCM5.02编译一 : 缺少工具链路
  5. Java 性能优化之 String 篇
  6. docker容器内部使用vim
  7. 区块链在供应链领域的应用
  8. 前端vue的get和post请求
  9. 【ArcGIS风暴】ArcGIS平台上点云(.las)数据生成等高线方法案例精解
  10. xpath中两个冒号_爬虫学习(5)—XPath
  11. ASP.NET Core与Dapper和VS 2017使用JWT身份验证WEB API并在Angular2客户端应用程序中使用它
  12. 隐藏与显现_原神:芭芭拉的隐藏彩蛋你知道吗?对着游戏npc用技能就可显现
  13. 目标检测——模型的快速验证
  14. 洛谷P1044 栈(Catalan数)
  15. 【HackerRank】Cut the tree
  16. html翻译插件,翻译插件:ImTranslator
  17. 敏感词库 包含中英文
  18. 我是不是应该离职?盖洛普Q12测评法
  19. QOS中 PQ,CQ.RR,WFQ,CBWFQ,LLQ区分
  20. payjs 源码_第三方支付平台源码,仿支付宝

热门文章

  1. 使用feign调用注解在eureka上的微服务,简单学会微服务
  2. docker :open /var/lib/docker/tmp/GetImageBlob318829910: no such file or directory异常解决
  3. 2022-2028年现代农业背景下中国家庭农场深度调研及投资前景预测报告
  4. Docker compose 容器编排
  5. Redis学习之路(一)--下载安装redis
  6. python 如何获取当前系统的时间
  7. SMOTE算法代码实现-机器学习
  8. 深度学习的Xavier初始化方法
  9. 自动驾驶QNX,Linux,Autosar概述
  10. 2021年大数据ZooKeeper(五):ZooKeeper Java API操作