NSTimer应用

在参与项目开发中遇到了NSTimer的应用,虽然我负责的模块内只用到了一小部分,但我觉得还是有必要拿出来好好琢磨一下。

一、概念(来自官方描述)

  官网上最新的定义是“A timer that fires after a certain time interval has elapsed, sending a specified message to a target object.” 也就是经过一定时间间隔后触发,向目标对象发送指定消息的计时器。

  1、概述

  定时器和run loops协同工作。而且run loops保持对定时器的强引用,所以不需要维护添加到run loops后的定时器。同时为了高效使用计时器,必了解run loops如何运行的。

  计时器不是一个实时生效的机制。如果定时器启动时刻正一个很长时间的callout或者run loop处于一个不再检测这个定时的模式,它将不启动直到run loop检测到下一个启动时刻。所以定时器真正开始生效的时间是在程序设定启动之后的一段时间内。

  NSTimer 是“tool-free bridge”模式,在Core Foundation中对应着CFRunLoopTimerRef。(几个专业名词对我来说真的有些陌生,小菜鸡真的还有很多要学习……)

  2、重复和非重复定时器

  在初始化定时器时,你需要明确这个定时器是否重复。 一个非重复的定时器触发一次后自动失效,从而阻止了定时器的再次触发。相反的是一个重复的定时器触发结束后重新把自己放到run loops中,准备下一次启动。重复计时器总是根据预定的触发时间来调度自己,而不是实际的触发时间。例如,如果一个定时器预定在某个特定的时间触发,每5秒之后,预定的触发时间将永远落在原来的5秒时间间隔内,哪怕是实际发射时间被推迟了。如果触发时间被延迟到通过一个或多个预定的触发间隔,则定时器仅在该时间内发射一次;然后触发后定时器被重新调度,为了未来预定下一次触发。

  3、定时器的容差

  在iOS 7 以及之后的版本和macOS 10.9以及之后的版本,你能指定定时器的容差。在定时器触发时,这个灵活性提高了系统的优化能力,以提高功耗和响应能力。定时器可能在任何预定的触发时间和预定加上容差的时间内触发,不会在预定的触发时间前触发。对于重复定时器,下一个触发时间是从初始的触发时间计算出来的,不管在单个触发时间内的容差,以免漂移。默认值是0,则意味着不使用额外的的容差。系统保留对部分定时器应用少量容差的权利,而不管容差的特性。

  作为定时器的使用者,你能决定定时器的适当容差。一条普遍的规则,将对至少10%的区间的容差设置为重复定时器。即使是少量的容错也会对应用程序的效率产生显著的积极影响。系统能强制执行容差的最大值。

  4、在Run Loops里安置定时器

  你能在一个唯一的run loops中注册一个定时器,尽管它可以被添加到run loops中的多个run loops模式中。这有三种新建定时器的方法:

  ·用方法 scheduledTimerWithTimeInterval:invocation:repeats: 或者
scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: 类方法来创建定时器,并在默认模式下被安置到当前的run loop上。

  ·用方法timerWithTimeInterval:invocation:repeats:  或者 timerWithTimeInterval:target:selector:userInfo:repeats:类方法来创建定时器对象,且无需在run loops上调度它。(创建后,必须手动安置到一个run loop里,通过调用NSRunLoop的函数 addTimer:forMode: )

  ·开辟资源并初始化定时器用 initWithFireDate:interval:target:selector:userInfo:repeats:方法。(同样,你必须手动安置到一个run loop里通过调用NSRunLoop的函数 addTimer:forMode: )

  一旦在run loops上调度,定时器就在指定的的间隔中触发,直到它失效为止。非重复的定时器在触发结束后立刻无效。但对于重复定时器,必须通过调用它的无效方法来使定时器对象无效。调用这个方法要求从当前的run loops中删除定时器,因此你应该在安装定时器的同一线程中调用无效方法。无效的定时器立即禁用为了不让它再影响run loop。之后run loop将删除定时器(以及对应的强引用),或者在还原方法返回前或稍后的某个时间点。一旦失效,定时器对象将不能被重用。

  在重复定时器触发后,它将调度最近间隔的的下一个触发,即在最后一次预定的触发时间内,在指定的容差范围内,定时器间隔的整倍数。如果调用执行选择器或者调用时间长于指定的间隔,则定时器只安排下一次触发。那是定时器为不试图弥补错过触发在调用指定的选择器或调用发生。

  5、子类注意事项

  不要尝试用NSTimer生成子类。

二、实例操作

  我应用到NSTimer的开发部分是为了实现发送验证码状态转换的按钮,实现效果如右动图       

  首先要在设置“发送验证码”按钮时做好接口

[self.sendVerificationCode addTarget:self action:@selector(pressGainCode:) forControlEvents:UIControlEventTouchUpInside];

  配置相关的方法(实例中我取名为pressGainCode),为了支持重复获取验证码的情况,我使用的是重复定时器。

 - (void)pressGainCode:(UIButton *)btn {
[self validationCodeTimer];
} - (void)validationCodeTimer{
__block int timeout = ; //倒计时时间
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, );
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, , ,queue);
dispatch_source_set_timer(_timer,dispatch_walltime(NULL, ),1.0*NSEC_PER_SEC, ); //每秒执行
dispatch_source_set_event_handler(_timer, ^{
if(timeout <= ){ //倒计时结束,关闭
dispatch_source_cancel(_timer);
dispatch_async(dispatch_get_main_queue(), ^{
self.sendVerificationCode.userInteractionEnabled = YES;
self.sendVerificationCode.enabled = YES;
[self.sendVerificationCode setTitle:@"重获验证码" forState:UIControlStateNormal];
});
}
else {
timeout--;
NSString *strTime = [NSString stringWithFormat:@"%d秒后重发",timeout];
dispatch_async(dispatch_get_main_queue(), ^{
self.sendVerificationCode.enabled = NO;
[self.sendVerificationCode setTitle:strTime forState:UIControlStateDisabled];
});
}
});
dispatch_resume(_timer);
}

参考资料:Apple官方文档 、四个实用demo 、定时器总结  、官文翻译及基础操作

NSTimer应用的更多相关文章

  1. Objective-C三种定时器CADisplayLink / NSTimer / GCD的使用

    OC中的三种定时器:CADisplayLink.NSTimer.GCD 我们先来看看CADiskplayLink, 点进头文件里面看看, 用注释来说明下 @interface CADisplayLin ...

  2. 解决NSTimer存在的内存泄漏的问题

    创建定时器会在一定的间隔后执行某些操作,一般大家会这样创建定时器,这样创建的定时,self对定时器有个引用,定时器对self也有个引用,造成了循环引用,最终造成了内存泄漏,如果定时器在做下载的操作就会 ...

  3. NSTimer

    NSTimer叫做“定时器”,它的作用如下 在指定的时间执行指定的任务 每隔一段时间执行指定的任务 调用下面的方法就会开启一个定时任务 + (NSTimer *)scheduledTimerWithT ...

  4. NSTimer整理总结

    对于定时器NSTimer,我们大家都不会陌生,在使用的时候,我们常常会遇到一些坑,例如:在Scrollview拖动时,timer会暂停:在子线程中如何创建一个定时器等.针对于一些我们所遇到的坑,我来总 ...

  5. ios - NSTimer中target的self是强引用问题

    当控制器ViewController跳转进入控制器OneViewController中的时候开启定时器,让定时器每隔一段时间打印一次,当OneViewController dismiss的时候,控制器 ...

  6. ios基础篇(二十三)—— 定时器NSTimer与图片的自动切换

    一.NSTimer NSTimer是一个能在从现在开始到后面的某一个时刻或者周期性的执行我们指定的方法的对象.可以按照一定的时间间隔,将制定的信息发送给目标对象.并更新某个对象的行为.你可以选择在未来 ...

  7. NSTimer “定时器”

    •NSTimer叫做“定时器”,它的作用如下 Ø在指定的时间执行指定的任务 Ø每隔一段时间执行指定的任务 Ø •调用下面的方法就会开启一个定时任务 + (NSTimer *)scheduledTime ...

  8. IOS OC 多任务定时器 NSRunLoop 管理 NSTimer

    下面有两种做法 1.使用日期组件 NSDateComponents 2.使用NSString 生成一个日期 //  创建一个日历对象 NSCalendar *calendar = [NSCalenda ...

  9. iOS NSTimer使用详解 开启、关闭、移除

    定时器定时器详解ios定时器关闭定时器NSTimer 一,要使用一个定时器首先要定义一个定时器: @property (strong, nonatomic) NSTimer *myTimer;//定时 ...

  10. NSTimer的使用[zhuang]

    NSTimer 的头文件 /* NSTimer.h Copyright (c) 1994-2015, Apple Inc. All rights reserved. */ #import <Fo ...

随机推荐

  1. GET 和 POST 请求的优缺点和误区

    Get和Post在面试中一般都会问到,一般的区别:(1)post更安全(不会作为url的一部分,不会被缓存.保存在服务器日志.以及浏览器浏览记录中)(2)post发送的数据更大(get有url长度限制 ...

  2. linux下用户操作

    在linux中添加ftp用,并设置相应的权限,操作步骤如下: 1.环境:ftp为vsftp.被限制用户名为test.被限制路径为/home/test. 2.建用户:在root用户下: useradd  ...

  3. work2:贪吃蛇

    学号:2017*****7219 姓名:邰嘉琛我的码云贪吃蛇项目仓库:https://gitee.com/tjc666/sesnake/tree/master2) 给出你的各项任务完成时间估算与实际消 ...

  4. springMVC控制器,处理器,映射器,适配器

    前端控制器DispatcherServlet <!--定义spring mvc 的前端控制器Servlet --><servlet> <!--Servlet的名称--&g ...

  5. 活代码LINQ——08

    一.模块代码 ' Fig. 9.6: ListCollection.vb ' Generic List collection demonstration. Module ListCollection ...

  6. Java线程面试题Top50

    不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题.Java 语言一个重要的特点就是内置了对并发的支持,让 Java 大受企业和程序员的欢迎.大多数待遇丰厚的 Java 开发职位都要求开发者 ...

  7. 声明一个set集合,使用HashSet类,来保存十个字符串信息,然后通过这个集合,然后使用iterator()方法,得到一个迭代器,遍历所有的集合中所有的字符串;然后拿出所有的字符串拼接到一个StringBuffer对象中,然后输出它的长度和具体内容; 验证集合的remove()、size()、contains()、isEmpty()等

    package com.lanxi.demo1_3; import java.util.HashSet; import java.util.Iterator; import java.util.Set ...

  8. 为什么Python是最适合初创公司的编程语言?

    为什么Python是最适合初创公司的编程语言? 选自Medium 作者:Gleb Pushkov 京东云开发者社区编译 对于初创公司而言,要在众多编程语言中为公司选择一个正确.合适的语言绝非易事. 如 ...

  9. shell中的数据生命周期scope

    #!/bin/shexit 0#shell 中, 默认所有的变量都是 全局变量,除非主动变量前面加 local 修饰#shell 变量是字符变量,只能放字符和数字,shell数组也是如此;而数字也是图 ...

  10. Python第一章(北理国家精品课 嵩天等)

    1.1程序设计基本方法 IPO 分析问题,划分边界,设计算法: 编写程序,调试测试,升级维护. 1.2Python开发环境配置 1.3实例1:温度转换 1.4Python程序语法元素分析 缩进,#添加 ...