iOS timer计时器

timer,计时器,就是用来计时的,可以将它和要处理的动作绑定起来,让这个动作在某段时间之后执行,或者周期性地执行。

一、timer的工作原理

timer的工作和run loop密不可分,由于平常我们使用Application Kit和UIKit来新建的app,在app的主线程启动的时候就自动启动了一个runloop,因此在主线程中使用timer感觉不到runloop的存在。如果要在分线程中使用timer,就必须要了解timer和runloop的协同工作原理,自己去新建runloop,让它和timer一起配合工作。

简短概括runloop和timer的工作关系就是,timer只负责计时,timer所绑定的动作,是由runloop来执行的。下面就来详细地讲讲这种关系。

我们知道,runloop运行的时候需要指定运行模式(run loop mode),runloop的运行模式规定了它要监听的事件源,以及事件发生时它要通知的对象。因此可以给runloop定义多种运行模式,runloop运行时,可以同时启用多个运行模式。

一个timer同一时间只可以注册到一个runloop中,但是可以添加到这个runloop的多个运行模式中。(下图表示了这个关系)

初始化一个timer,就是给timer绑定一个要执行的动作;登记一个时间段,这个时间段用来告诉runloop,该动作需要在该时间段过去之后执行,或者每隔这个时间段执行一次。

在timer与runloop的协同工作中,timer只负责计时,而runloop负责监视其所启用的运行模式中添加的timer是否已经达到了其初始化时登记的时间,一旦发现某个timer已经到达了这个时间,就会去执行该timer所绑定的动作(这就是所谓的fire the timer)。

由此可以见得,timer所登记的这个时间段并不是动作的绝对执行时间。timer绑定的动作具体在什么时候执行,要看runloop是否在运行,且是否启用了timer所加入的运行模式,还要看runloop正在处理的东西多不多,能不能及时发现timer已经计时完毕。

二、timer的具体使用

1、创建timer

(1)使用当前的runloop来创建一个timer

方法:

+ (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;

参数TimeInterval是timer计时的周期长度,每隔时长TimeInterval,计时器就会清零一次。

这两个方法,完成一系列动作:

  • 创建timer;
  • 将它加入到当前runloop的默认运行模式中;
  • 让timer开始计时。

对于这种方式添加的timer,runloop就会等它的计时时长第一次达到TimeInterval时,才会执行它绑定的动作。

(2)自己新建一个timer,之后将它注册到某个runloop中

方法:

+ (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;

这两个方法可以返回一个timer。

之后要用runloop对象的方法将timer注册到这个runloop对象的某个运行模式中:

-(void)addTimer:(nonnull NSTimer *) forMode:(nonnull NSString *);

这样添加到runloop的timer会立即开始计时。

(3)初始化一个timer,并指明它绑定的动作被执行的时间点

方法:

- (instanceType)initWithFireDate:(nonnull NSDate *) interval:(NSTimeInterval) target:(nonnull id) selector:(nonnull SEL) userInfo:(nullable id) repeats:(BOOL);

这里的fireDate是个时间点,是相对于系统时间的,只要到达了这个时间点,runloop就会去执行timer绑定的动作。所以如果timer是一次性的,都不需要计时,interval这个参数就没有作用了。如果是重复的timer,才需要计时,参数interval才有用。

可以用setFireDate方法来给timer设定动作的执行时间。

2、停止timer

timer需要在runloop的管理下才会有效,停止timer,只要把它从它所在的runloop中清理掉就可以实现。(或者让runloop停止运行)。

(1)对于一次性的timer

一次性的timer都不用考虑这个问题,因为runloop执行完timer绑定的动作就会自动把这个timer从它所在的运行模式中清理掉。

(2)对于周期性的timer

方法:

-(void)invalidate;

对于周期性的timer才需要考虑这个问题。

要停止一个周期性的timer,要获取这个timer对象的引用,在需要清理timer的时候,主动调用该timer对象的invalidate方法即可。

当然,也可以对一次性的timer执行这个方法,在timer的动作被runloop执行之前调用invalidate方法,timer的动作就永远不会被执行了。

时间: 2024-10-18 13:20:55

iOS timer计时器的相关文章

java中基于timer计时器的图片播放

所有注释放在代码中...(图片的加入使用硬代码) package com.sxt.jtime; import java.awt.BorderLayout; public class Itimer_test extends JFrame { private JPanel contentPane; private int index = 0;//图片播放计数器 private ImageIcon[] img;//声明数组用来存放要播放的图片 JLabel label;//声明为全局变量用来显示图片

go语言示例-Timer计时器的用法

计时器用来定时执行任务,分享一段代码: package main import "time" import "fmt" func main() { //新建计时器,两秒以后触发,go触发计时器的方法比较特别,就是在计时器的channel中发送值 timer1 := time.NewTimer(time.Second * 2) //此处在等待channel中的信号,执行此段代码时会阻塞两秒 <-timer1.C fmt.Println("Timer 1

iOS 中计时器的使用心得

1. NSTimer 使用NSTimer开启的计时器,如果拖动scrollView会导致计时器暂停,并且锁屏的时候必须暂停计时器,否则抛异常. 暂停计时器方法 [_sTimer setFireDate:[NSDate distantFuture]]; 恢复计时器方法 [_sTimer setFireDate:[NSDate distantPast]]; _sTimer = [NSTimer scheduledTimerWithTimeInterval:interval target:timerT

Timer计时器

public Form2() { InitializeComponent(); m_Timer(); } void m_Timer() { System.Timers.Timer t = new System.Timers.Timer(10000); //实例化Timer类,设置间隔时间为10000毫秒: t.Elapsed += new System.Timers.ElapsedEventHandler(theout); //到达时间的时候执行事件: t.AutoReset = true; /

Global中的Timer计时器

protected void Application_Start(object sender, EventArgs e)//端口启动的事件        {            Hzjg.Common.Utility.Log.FilePath = Server.MapPath("~/") + "\\log"; // 在应用程序启动时运行的代码              System.Timers.Timer myTimer = new System.Timers.

iOS 计时器三种定时器的用法NSTimer、CADisplayLink、GCD

原文:http://www.cocoachina.com/ios/20160919/17595.html 一.三种计时器 二.全局倒计时 #import "ViewController.h" @interface ViewController () { CADisplayLink * displaylinked; } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do

Timer TimerTask CountDown 计时器 API

Timer 计时器 一种工具,线程用其安排以后在后台线程中执行的任务.可安排任务执行一次,或者定期重复执行. 与每个 Timer 对象相对应的是单个后台线程,用于顺序地执行所有计时器任务.计时器任务应该迅速完成.如果完成某个计时器任务的时间太长,那么它会"独占"计时器的任务执行线程.因此,这就可能延迟后续任务的执行,而这些任务就可能"堆在一起",并且在上述不友好的任务最终完成时才能够被快速连续地执行. 对 Timer 对象最后的引用完成后,并且 所有未处理的任务都已

iOS下日期的处理

NSDate存储的是世界标准时(UTC),输出时需要根据时区转换为本地时间 Dates         NSDate类提供了创建date,比较date以及计算两个date之间间隔的功能.Date对象是不可改变的.         如果你要创建date对象并表示当前日期,你可以alloc一个NSDate对象并调用init初始化: C代码  NSDate *now = [[NSDate alloc] init];                或者使用NSDate的date类方法来创建一个日期对象.

Timer与ScheduledExecutorService间的抉择

java.util.Timer计时器有管理任务延迟执行("如1000ms后执行任务")以及周期性执行("如每500ms执行一次该任务").但是,Timer存在一些缺陷,因此你应该考虑使用ScheduledThreadPoolExecutor作为代替品,Timer对调度的支持是基于绝对时间,而不是相对时间的,由此任务对系统时钟的改变是敏感的;ScheduledThreadExecutor只支持相对时间. Timer的另一个问题在于,如果TimerTask抛出未检查的异