NSTimer应用
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应用的更多相关文章
- Objective-C三种定时器CADisplayLink / NSTimer / GCD的使用
OC中的三种定时器:CADisplayLink.NSTimer.GCD 我们先来看看CADiskplayLink, 点进头文件里面看看, 用注释来说明下 @interface CADisplayLin ...
- 解决NSTimer存在的内存泄漏的问题
创建定时器会在一定的间隔后执行某些操作,一般大家会这样创建定时器,这样创建的定时,self对定时器有个引用,定时器对self也有个引用,造成了循环引用,最终造成了内存泄漏,如果定时器在做下载的操作就会 ...
- NSTimer
NSTimer叫做“定时器”,它的作用如下 在指定的时间执行指定的任务 每隔一段时间执行指定的任务 调用下面的方法就会开启一个定时任务 + (NSTimer *)scheduledTimerWithT ...
- NSTimer整理总结
对于定时器NSTimer,我们大家都不会陌生,在使用的时候,我们常常会遇到一些坑,例如:在Scrollview拖动时,timer会暂停:在子线程中如何创建一个定时器等.针对于一些我们所遇到的坑,我来总 ...
- ios - NSTimer中target的self是强引用问题
当控制器ViewController跳转进入控制器OneViewController中的时候开启定时器,让定时器每隔一段时间打印一次,当OneViewController dismiss的时候,控制器 ...
- ios基础篇(二十三)—— 定时器NSTimer与图片的自动切换
一.NSTimer NSTimer是一个能在从现在开始到后面的某一个时刻或者周期性的执行我们指定的方法的对象.可以按照一定的时间间隔,将制定的信息发送给目标对象.并更新某个对象的行为.你可以选择在未来 ...
- NSTimer “定时器”
•NSTimer叫做“定时器”,它的作用如下 Ø在指定的时间执行指定的任务 Ø每隔一段时间执行指定的任务 Ø •调用下面的方法就会开启一个定时任务 + (NSTimer *)scheduledTime ...
- IOS OC 多任务定时器 NSRunLoop 管理 NSTimer
下面有两种做法 1.使用日期组件 NSDateComponents 2.使用NSString 生成一个日期 // 创建一个日历对象 NSCalendar *calendar = [NSCalenda ...
- iOS NSTimer使用详解 开启、关闭、移除
定时器定时器详解ios定时器关闭定时器NSTimer 一,要使用一个定时器首先要定义一个定时器: @property (strong, nonatomic) NSTimer *myTimer;//定时 ...
- NSTimer的使用[zhuang]
NSTimer 的头文件 /* NSTimer.h Copyright (c) 1994-2015, Apple Inc. All rights reserved. */ #import <Fo ...
随机推荐
- SpringBoot是什么,可以做什么?
SpringBoot简析 1.SpringBoot是什么? 在Spring框架这个大家族中,产生了很多衍生框架,比如 Spring.SpringMvc框架等,Spring的核心内容在于控制反转( ...
- 移动App测试中的最佳做法
一说起软件测试,测试员想到肯定是去检查文件,功能,API,性能并确定软件是否安全,以及关于软件特定部分的其他事项.但是对于移动测试,测试员不得不基于用户移动使用模式考虑移动相关的功能. 本文是基于我的 ...
- Arrlist的重要方法重写
import java.util.Arrays; public class ArrayOperator { public static void main(String[] args) { // TO ...
- bootstrap全局样式二
加form-grope是为了以后更好的管理,一组form写一个form-grope 显示如下: 并排显示的话,给用户名前面再加一个div,再加horizontal,如下,并且加上control-lab ...
- python中的turtle库(图形绘画库)
turtle绘图的基础知识:1. 画布(canvas) 画布就是turtle为我们展开用于绘图区域,我们可以设置它的大小和初始位置. 设置画布大小 turtle.screensize(canvwidt ...
- [数]青蛙的约会&Strange function
拓展欧几里得:求导&二分 POJ-1061 拓展欧几里得的应用,需要开long long 第一次做这个题的时候进行了毫无用处的找公式(?),是个现在的我看不懂的迷之思路. 第二发的时候还是不明 ...
- laravel(lumen)配置读写分离后,强制读主(写)库数据库,解决主从延迟问题
在Model里面加上下面这句,强制读主(写)库数据库,解决主从延迟问题. public static function boot() { //清空从连接,会自动使用主连接 DB::connection ...
- java LRUCache
package org.rx.cache; import org.rx.common.*; import org.rx.beans.DateTime; import java.util.Collect ...
- windows7 下jdk1.8 改为 1.7过程,及环境变量配置;
一. 安装完成后 当然是配置环境变量: JAVA_HOME 是我们以后用到jdk所在位置的内容时为了方便,给jdk起的名字,也是java程序约定的变量名,如果没有,当你在cmd 输入 java ja ...
- 日积月累---JVM01
Java体系结构包括四个独立但相关的技术: Java程序设计语言 Java class文件格式 Java应用编程接口 Java虚拟机 用Java编程语言编写源代码,把它编译成Java class文件, ...