我如何使用NSTimer?
我如何使用NSTimer
? 任何人都可以给我一步一步的指示?
首先,我想提请您注意Cocoa / CF文档(这始终是一个很好的第一停靠点)。 Apple文档在每篇参考文章的顶部都有一个名为“Companion Guides”的部分,其中列出了所logging主题(如果存在的话)的指南。 例如,在NSTimer
, 文档列出了两个配套指南:
- 计时器编程主题为cocoa
- 线程编程指南
对于您的情况,计时器编程专题文章可能是最有用的,而线程主题是相关的,但不直接与被logging的类相关。 如果您看一下定时器编程主题文章,它分为两部分:
- 计时器
- 使用定时器
对于采用这种格式的文章,通常会有关于类的概述和用法,以及关于如何使用它的示例代码,在这种情况下,在“使用计时器”部分。 有“创build和计划定时器”,“停止计时器”和“内存pipe理”部分。 从文章中,创build一个计划,不重复的计时器可以这样做:
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(targetMethod:) userInfo:nil repeats:NO];
这将创build一个计时器,在2.0秒后触发,并调用targetMethod:
在一个self
variables上,这是一个指向NSTimer
实例的指针。
如果您希望更详细地了解该方法,则可以参考文档以获取更多信息,但是也会对代码进行解释。
如果你想停止一个重复的定时器,(或者在它触发之前停止一个不重复的定时器),那么你需要保留一个指向创build的NSTimer
实例的指针; 通常这将需要是一个实例variables,以便您可以用另一种方法引用它。 然后你可以在NSTimer
实例上调用invalidate
:
[myTimer invalidate]; myTimer = nil;
将实例variables清零也是一个好习惯(例如,如果你的方法使得定时器无效被多次调用,并且实例variables没有被设置为nil
,并且NSTimer
实例已经被释放,则会抛出exception) 。
请注意文章底部的“内存pipe理”一节:
因为运行循环维护定时器,所以从内存pipe理的angular度来看, 在计划完成之后通常不需要保留对定时器的引用 。 由于当您将其方法指定为select器时,计时器将作为parameter passing,因此可以在该方法内适当的时候使重复计时器无效 。 然而,在许多情况下,您还需要使计时器无效 – 也许甚至在启动之前。 在这种情况下,您需要保持对定时器的引用,以便在适当的时候发送无效消息 。 如果你创build一个不定时的定时器(见“非定时定时器”),那么你必须保持对定时器的强引用(在一个引用计数的环境中,你保留它),这样在你使用它之前不会释放它。
有一些使用计时器的方法:
1) 预定定时器和使用select器
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 2.0 target: self selector:@selector(onTick:) userInfo: nil repeats:NO];
- 如果将重复设置为NO,则定时器将在运行select器之前等待2秒钟,之后将停止;
- 如果重复:YES,定时器将立即启动,并将每2秒重复调用select器;
- 停止定时器,你调用定时器的无效方法:[t invalidate];
作为一个方面的说明,而不是使用一个不重复,并在指定的时间间隔后调用select器的计时器,你可以使用这样一个简单的语句:
[self performSelector:@selector(onTick:) withObject:nil afterDelay:2.0];
这将与上面的示例代码具有相同的效果; 但是如果要每隔第n次调用一次select器,则使用带有重复的定时器:YES;
2) 自我计划的计时器
NSDate *d = [NSDate dateWithTimeIntervalSinceNow: 60.0]; NSTimer *t = [[NSTimer alloc] initWithFireDate: d interval: 1 target: self selector:@selector(onTick:) userInfo:nil repeats:YES]; NSRunLoop *runner = [NSRunLoop currentRunLoop]; [runner addTimer:t forMode: NSDefaultRunLoopMode]; [t release];
- 这将创build一个计时器,它将在您指定的自定义date(在这种情况下,一分钟后)自行启动,并且每隔一秒重复一次
3) 计划外的计时器和使用调用
NSMethodSignature *sgn = [self methodSignatureForSelector:@selector(onTick:)]; NSInvocation *inv = [NSInvocation invocationWithMethodSignature: sgn]; [inv setTarget: self]; [inv setSelector:@selector(onTick:)]; NSTimer *t = [NSTimer timerWithTimeInterval: 1.0 invocation:inv repeats:YES];
在此之后,您需要像这样手动启动计时器:
NSRunLoop *runner = [NSRunLoop currentRunLoop]; [runner addTimer: t forMode: NSDefaultRunLoopMode];
注意,onTick:方法如下所示:
-(void)onTick:(NSTimer *)timer { //do smth }
像这样的东西:
NSTimer *timer; timer = [NSTimer scheduledTimerWithTimeInterval: 0.5 target: self selector: @selector(handleTimer:) userInfo: nil repeats: YES];
#import "MyViewController.h" @interface MyViewController () @property (strong, nonatomic) NSTimer *timer; @end @implementation MyViewController double timerInterval = 1.0f; - (NSTimer *) timer { if (!_timer) { _timer = [NSTimer timerWithTimeInterval:timerInterval target:self selector:@selector(onTick:) userInfo:nil repeats:YES]; } return _timer; } - (void)viewDidLoad { [super viewDidLoad]; [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; } -(void)onTick:(NSTimer*)timer { NSLog(@"Tick..."); } @end
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timerCalled) userInfo:nil repeats:NO]; -(void)timerCalled { NSLog(@"Timer Called"); // Your Code }
答案是缺less一个特定的时间计时器在这里是在下一个小时:
NSCalendarUnit allUnits = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; NSCalendar *calendar = [[ NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; NSDateComponents *weekdayComponents = [calendar components: allUnits fromDate: [ NSDate date ] ]; [ weekdayComponents setHour: weekdayComponents.hour + 1 ]; [ weekdayComponents setMinute: 0 ]; [ weekdayComponents setSecond: 0 ]; NSDate *nextTime = [ calendar dateFromComponents: weekdayComponents ]; refreshTimer = [[ NSTimer alloc ] initWithFireDate: nextTime interval: 0.0 target: self selector: @selector( doRefresh ) userInfo: nil repeats: NO ]; [[NSRunLoop currentRunLoop] addTimer: refreshTimer forMode: NSDefaultRunLoopMode];
当然,用你的class级所需的方法来替代“doRefresh”
尝试一次创build日历对象,并使allUnit静态以提高效率。
添加一个小时的组件工作得很好,不需要午夜testing( 链接 )