NSTImer重复执行任务
问题
应用需要调度代码以在特定的时间执行。此外,你还想要重复执行任务。
解决方案
使用NSTimer调度代码以在特定的时间执行。为了使用NSTimer,你需要有日期对象与指向应用的运行循环的引用。
注意:
NSTimer需要有运行循环,如果想在Mac或iOS应用中使用定时器,就必须有运行循环。本攻略需要应用带有运行循环。1.11与1.12节分别介绍了创建Mac与iOS应用的步骤。
说明
本攻略的代码位于应用委托中。通常情况下,定时器会放在自定义类或是应用控制器中。
定时器会从特定的日期与时间开始向对象发送消息。如果应用需要重复,那么定时器可能会间隔一段时间后再发送消息。你首先需要有日期对象,用来表示定时器开始向对象发送消息的日期与时间: 
NSDate *scheduledTime = [NSDate dateWithTimeIntervalSinceNow:10.0];
上述调度时间位于上面这一行代码执行后的10秒钟。可以在这里使用任何日期。
接下来,通过initWithFireDate:interval:target:selector:userInfo:repeats:构造函数创建定时器: 
SString *customUserObject = @"To demo userInfo";
NSTimer *timer = [[NSTimer alloc] initWithFireDate:scheduledTime 
                                          interval:2 
                                            target:self 
                                          selector:@selector(task) 
                                          userInfo:customUserObject 
                                           repeats:YES];
这里有些内容需要说明一下。第1个参数是日期对象,指定了定时器何时变成活动状态。接下来是间隔时间,是定时器再次发送消息前所需等待的秒数。之后是目标参数描述符,目标是方法所处的对象。selector参数是位于圆括号中的方法名,前面是@selector关键字。由于方法与定时器一样都位于应用委托中,因此可以使用self关键字。
userInfo是定时器使用的自定义内容。可以使用任何对象,并且可以获得正在执行的消息中的对象引用(上面的selector参数)。这里使用了字符串,但通常会使用字典或其他集合以支持更加复杂的活动。
repeats参数表示定时器是发送一次消息,还是根据第2个参数指定的时间间隔重复发送。
接下来需要指向运行循环的引用。可以通过NSRunLoop的currentRunLoop函数获得该引用: 
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
现在,只需要将定时器添加到运行循环中即可: 
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
10秒钟后,定时器将会开始每隔两秒钟向应用发送task消息。
启动之后,如果想停止定时器,可以向定时器发送invalidate消息。这会从运行循环中删除定时器,代码如下所示: 
[timer invalidate];
参见程序清单5-7。
代码
程序清单5-7 main.m 
#import "AppDelegate.h"
@implementation AppDelegate 
@synthesize window = _window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{ 
    NSDate *scheduledTime = [NSDate dateWithTimeIntervalSinceNow:10.0]; 
    NSString *customUserObject = @"To demo userInfo"; 
    NSTimer *timer = [[NSTimer alloc] initWithFireDate:scheduledTime 
                                              interval:2 
                                                target:self 
                                              selector:@selector(task) 
                                              userInfo:customUserObject 
                                               repeats:YES]; 
    NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; 
    [runLoop addTimer:timer forMode:NSDefaultRunLoopMode]; 
}
-(void)task:(id)sender{ 
    NSTimer *localTimer = (NSTimer *)sender; 
    NSLog(@"Schedule task has executed with this user info: %@", [localTimer  userInfo]); 
}
@end
使用
要想使用上述代码,请从Xcode构建并运行Mac应用。注意控制台窗口以及消息何时开始打印到日志中。此处打印出了时间戳,这样就可以看到时间间隔的运作方式了: 
2012-01-19 15:23:28.651 Timer[31067:707] Schedule task has executed with  this user info: To demo userInfo 
2012-01-19 15:23:30.651 Timer[31067:707] Schedule task has executed with  this user info: To demo userInfo 
2012-01-19 15:23:32.651 Timer[31067:707] Schedule task has executed with  this user info: To demo userInfo
NSTImer重复执行任务的更多相关文章
- remove name="ProxyModule“会导致重复执行
		
<?xml version="1.0" encoding="utf-8"?> <!-- 有关如何配置 ASP.NET 应用程序的详细信息,请访 ...
 - jquery 实现重复点击一个元素时不重复执行效果
		
jquery 实现重复点击一个元素时不重复执行效果 这需要用到jquery的stop方法 实例 停止当前正在运行的动画: $("#stop").click(function(){ ...
 - Spring的quartz定时器同一时刻重复执行二次的问题解决
		
最近用Spring的quartz定时器的时候,发现到时间后,任务总是重复执行两次,在tomcat或jboss下都如此. 打印出他们的hashcode,发现是不一样的,也就是说,在web容器启动的时候, ...
 - jquery click点击事件重复执行多次
		
$("button[name^='privateBtn']").click(function(){ alert('demo'); //接触绑定.避免重复执行 $("but ...
 - jQuery使用伪递归重复执行动画
		
使用setInterval()来重复执行动画,会因为动画执行过程的时候,setInterval()的时间依然是在走的,所以会导致动画的调用时间不理想,因此只能使用递归来重复执行动画. // 首页LOG ...
 - 使用定时器实现JavaScript的延期执行或重复执行
		
使用定时器实现JavaScript的延期执行或重复执行 window 对象提供了两个方法来实现定时器的效果,分别是window.setTimeout()和 window.setInterval.其中前 ...
 - Linux重复执行上条命令
		
Linux系统下Shell重复执行上条命令的 4 种方法: 1.使用上方向键,并回车执行.2.按 !! 并回车执行.3.输入 !-1 并回车执行.4.按 Ctrl+P 并回车执行.
 - java之生成可重复执行的sql脚本
		
在实际项目开发过程中,sql脚本需要多次执行.而一般的DML和DDL语句一般只能执行一次,再次执行执行时就会报错(操作对应已存在/不存在),所以必须将sql脚本生成可重复执行的.本文共分为4部分:1. ...
 - 可重复执行的SQL Script
		
问题 在工作中偶尔会遇到这样的问题:SQL script重复执行时会报错. 理想的状态下,SQL script跑一遍就够了,是不会重复执行的,但是实际情况往往很复杂. 比如Dev同学在开发时在A环境把 ...
 
随机推荐
- 1045 | error connecting to master 'slave_user@192.168.0.75:3306' - retry-time: 6
			
mysql 主从复制问题整理 问题: 1045 | error connecting to master 'slave_user@192.168.0.75:3306' - retry-t ...
 - 利用SCI做的一个足球答题系统
			
SCI,异步串行通信接口,内置独立的波特率产生电路和SCI收发器,可以选择发送8或9个数据位(其中一位可以指定为奇或偶校验位). SCI是全双工异步串行通信接口,主要用于MCU与其他计算机或设备之间的 ...
 - AutoHotKey 脚本集中营(一)
			
前言:实战是最好的学习.本集中营共分 x+mc2 期(x 为已发行的期数,m 为我的空闲时间,c 为我的更新动力),旨在通过对脚本代码的阅读而提高 AHK 语言的熟练程度.脚本的难度与期数成正比,有兴 ...
 - hdu 2709 Sumsets
			
Sumsets Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
 - ubuntu共享文件夹给virtualbox
			
在ubuntu或者linuxmint等linux系统下安装了virtualbox,可以通过共享文件夹的方式,把文件夹共享给virtualbox下的虚拟机系统,我这里的虚拟机系统是win7,共享过程如下 ...
 - Spring(3.2.3) - Beans(5): 集合属性的注入
			
如果 Bean 的属性是个集合,则可以使用 <list/>.<set/>.<map/> 和 <props/> 元素向 List.Set.Map 和 Pr ...
 - 【Knockout】四、绑定上下文
			
Binding context binding context是一个保存数据的对象,你可以在你的绑定中引用它.当应用绑定的时候,knockout自动创建和管理binding context的继承关系. ...
 - 在Delphi中,关于数组名称
			
动态数组数组名代表的是第一个元素的内存地址. 静态数组名称代表的是数组第一个元素的内存位置, 而不是数组第一个元素的内存地址. 但对于静态数组,在某些情况下编译器可能会自动取数组地址,如: funct ...
 - Oracle学习第二天---Profile的使用
			
环境:Oracle 11g 一.权限的传递 1.如果传递的是对象权限,就在后面加入with grant option: eg:system用户有张temp的表,只想usertest用户拥有查询的权限, ...
 - MacBook Pro 的照相机在哪?
			
用于拍照 用于录制视频