如何使用NSTimer?谁能给我一步一步的指导?
NSTimer
就像这样:
NSTimer *timer; timer = [NSTimer scheduledTimerWithTimeInterval: 0.5 target: self selector: @selector(handleTimer:) userInfo: nil repeats: YES];
首先,我想让您注意一下Cocoa/CF文档(这总是一个很好的第一步)。苹果文档在每篇参考文章的顶部都有一个叫做“Companion Guides”的部分,它列出了所记录主题的指南(如果存在的话)。例如,对于NSTimer, 的文档列出了两个配套指南:
对于您的情况,定时器编程主题文章可能是最有用的,而线程主题与所记录的类相关,但不是最直接的相关。如果你看一看定时器编程主题的文章,它分为两部分:
对于采用这种格式的文章,通常有一个类的概述和它的用途,然后是如何上的一些示例代码来使用它,在本例中是“使用计时器”一节。有“创建和调度定时器”,“停止定时器”和“内存管理”部分。在本文中,可以这样创建一个定时的、不重复的计时器:
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(targetMethod:) userInfo:nil repeats:NO];
这将创建一个计时器,在2.0秒后触发,并使用一个参数在self上调用targetMethod:,该参数是指向NSTimer实例的指针。
self
targetMethod:
如果你想更详细地了解这个方法,你可以参考文档获取更多信息,但是关于代码也有解释。
如果你想停止一个重复的计时器(或在非重复计时器触发之前停止它),那么你需要保留一个指向创建的NSTimer实例的指针;通常这需要是一个实例变量,以便您可以在另一个方法中引用它。然后你可以在NSTimer实例上调用invalidate:
invalidate
[myTimer invalidate]; myTimer = nil;
nil out实例变量也是一个很好的实践(例如,如果你的使计时器失效的方法被调用了不止一次,而实例变量还没有被设置为nil,并且NSTimer实例已经被释放,它将抛出异常)。
nil
还要注意文章末尾关于内存管理的观点:
因为运行循环维护计时器,从内存管理的角度在你安排了一个定时器之后,通常不需要保持对它的引用。由于计时器是在指定它的方法作为选择器时作为参数传递的,因此您可以在该方法中适当的时候使重复计时器失效. 您可以在该方法中适当的时候使重复计时器失效。然而,在许多情况下,您还需要使计时器失效的选项——甚至可能在它开始之前。在这种情况下,您确实需要保留对计时器的引用,以便在适当的时候向它发送无效消息。如果您创建了一个未调度定时器(请参阅“未调度定时器”),那么您必须维护对该定时器的强引用(在引用计数环境中,您保留它),以便在使用它之前不会释放它。
有几种使用计时器的方法:
1) 定时定时器&使用选择器
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 2.0 target: self selector:@selector(onTick:) userInfo: nil repeats:NO];
作为旁注,与其使用不重复的计时器,并在指定的间隔后调用选择器,不如使用如下简单的语句:
[self performSelector:@selector(onTick:) withObject:nil afterDelay:2.0];
这将与上面的示例代码具有相同的效果;但如果你想每n次调用一次选择器,你可以使用重复的计时器:YES; < / p >
2) self-scheduled计时器
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];
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];
-(void)onTick:(NSTimer *)timer { //do smth }
答案中缺少一个特定的时间,这里是下一个小时:
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];
当然,用类所需的方法替换“doRefresh”
尝试创建一次日历对象,并使allUnits为静态的效率。
添加一个小时组件工作得很好,不需要午夜测试(链接)
#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 }