objective-c 我如何使用 NSTimer?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1449035/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I use NSTimer?
提问by lab12
How do I use an NSTimer? Can anyone give me step by step instructions?
我如何使用NSTimer? 谁能给我一步一步的指示?
回答by Alex Rozanski
Firstly I'd like to draw your attention to the Cocoa/CF documentation (which is always a great first port of call). The Apple docs have a section at the top of each reference article called "Companion Guides", which lists guides for the topic being documented (if any exist). For example, with NSTimer, the documentationlists two companion guides:
首先,我想提请您注意 Cocoa/CF 文档(这始终是一个很好的首选)。Apple 文档在每篇参考文章的顶部都有一个名为“Companion Guides”的部分,其中列出了所记录主题的指南(如果存在)。例如,使用NSTimer,文档列出了两个配套指南:
For your situation, the Timer Programming Topics article is likely to be the most useful, whilst threading topics are related but not the most directly related to the class being documented. If you take a look at the Timer Programming Topics article, it's divided into two parts:
对于您的情况,Timer Programming Topics 文章可能是最有用的,而线程主题与所记录的类相关但不是最直接相关的。如果你看一下 Timer Programming Topics 文章,它分为两部分:
- Timers
- Using Timers
- 计时器
- 使用定时器
For articles that take this format, there is often an overview of the class and what it's used for, and then some sample code on howto use it, in this case in the "Using Timers" section. There are sections on "Creating and Scheduling a Timer", "Stopping a Timer" and "Memory Management". From the article, creating a scheduled, non-repeating timer can be done something like this:
对于采用这种格式的文章,通常会提供类及其用途的概述,然后是有关如何使用它的一些示例代码,在本例中位于“使用计时器”部分。有关于“创建和调度计时器”、“停止计时器”和“内存管理”的部分。从文章中,创建一个预定的、非重复的计时器可以这样做:
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:@selector(targetMethod:)
userInfo:nil
repeats:NO];
This will create a timer that is fired after 2.0 seconds and calls targetMethod:on selfwith one argument, which is a pointer to the NSTimerinstance.
这将创建为2.0秒后发射并调用计时器targetMethod:上self有一个说法,这是一个指向NSTimer实例。
If you then want to look in more detail at the method you can refer back to the docs for more information, but there is explanation around the code too.
如果您想更详细地查看该方法,您可以参考文档以获取更多信息,但也有关于代码的解释。
If you want to stop a timer that is one which repeats, (or stop a non-repeating timer before it fires) then you need to keep a pointer to the NSTimerinstance that was created; often this will need to be an instance variable so that you can refer to it in another method. You can then call invalidateon the NSTimerinstance:
如果你想停止一个重复的计时器(或者在它触发之前停止一个非重复的计时器),那么你需要保留一个指向NSTimer创建的实例的指针;通常这需要是一个实例变量,以便您可以在另一种方法中引用它。然后您可以调用invalidate该NSTimer实例:
[myTimer invalidate];
myTimer = nil;
It's also good practice to nilout the instance variable (for example if your method that invalidates the timer is called more than once and the instance variable hasn't been set to niland the NSTimerinstance has been deallocated, it will throw an exception).
nil删除实例变量也是一种很好的做法(例如,如果多次调用使计时器无效的方法并且实例变量尚未设置nil并且NSTimer实例已被释放,它将抛出异常)。
Note also the point on Memory Management at the bottom of the article:
还要注意文章底部关于内存管理的观点:
Because the run loop maintains the timer, from the perspective of memory management there's typically no need to keep a reference to a timer after you've scheduled it. Since the timer is passed as an argument when you specify its method as a selector, you can invalidate a repeating timer when appropriate within that method. In many situations, however, you also want the option of invalidating the timer—perhaps even before it starts. In this case, you do need to keep a reference to the timer, so that you can send it an invalidate message whenever appropriate. If you create an unscheduled timer (see “Unscheduled Timers”), then you must maintain a strong reference to the timer (in a reference-counted environment, you retain it) so that it is not deallocated before you use it.
因为运行循环维护计时器,所以从内存管理的角度来看,通常不需要在您安排计时器后保留对计时器的引用。由于当您将其方法指定为选择器时,计时器作为参数传递,因此您可以在该方法中适当时使重复计时器无效。然而,在许多情况下,您还需要使计时器无效的选项——甚至可能在它开始之前。在这种情况下,您确实需要保留对计时器的引用,以便您可以在适当的时候向其发送无效消息. 如果你创建了一个非调度定时器(参见“非调度定时器”),那么你必须维护一个对定时器的强引用(在引用计数的环境中,你保留它),这样它在你使用之前不会被释放。
回答by Woofy
there are a couple of ways of using a timer:
有几种使用计时器的方法:
1) scheduled timer & using selector
1)预定定时器 & 使用选择器
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 2.0
target: self
selector:@selector(onTick:)
userInfo: nil repeats:NO];
- if you set repeats to NO, the timer will wait 2 seconds before running the selector and after that it will stop;
- if repeat: YES, the timer will start immediatelly and will repeat calling the selector every 2 seconds;
- to stop the timer you call the timer's -invalidate method: [t invalidate];
- 如果您将重复设置为 NO,则计时器将在运行选择器之前等待 2 秒,之后它将停止;
- 如果repeat: YES,定时器将立即启动并每2秒重复调用一次选择器;
- 要停止计时器,您可以调用计时器的 -invalidate 方法:[t invalidate];
As a side note, instead of using a timer that doesn't repeat and calls the selector after a specified interval, you could use a simple statement like this:
作为旁注,您可以使用这样的简单语句,而不是使用不重复并在指定时间间隔后调用选择器的计时器:
[self performSelector:@selector(onTick:) withObject:nil afterDelay:2.0];
this will have the same effect as the sample code above; but if you want to call the selector every nth time, you use the timer with repeats:YES;
这将与上面的示例代码具有相同的效果;但是如果你想每 n 次调用选择器,你可以使用带有 repeats:YES; 的计时器。
2) self-scheduled timer
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];
- this will create a timer that will start itself on a custom date specified by you (in this case, after a minute), and repeats itself every one second
- 这将创建一个计时器,该计时器将在您指定的自定义日期启动(在本例中,一分钟后),并每隔一秒重复一次
3) unscheduled timer & using invocation
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];
and after that, you start the timer manually whenever you need like this:
之后,您可以在需要时手动启动计时器,如下所示:
NSRunLoop *runner = [NSRunLoop currentRunLoop];
[runner addTimer: t forMode: NSDefaultRunLoopMode];
And as a note, onTick: method looks like this:
请注意, onTick: 方法如下所示:
-(void)onTick:(NSTimer *)timer {
//do smth
}
回答by ennuikiller
Something like this:
像这样的东西:
NSTimer *timer;
timer = [NSTimer scheduledTimerWithTimeInterval: 0.5
target: self
selector: @selector(handleTimer:)
userInfo: nil
repeats: YES];
回答by Dan
#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
回答by Mohit
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timerCalled) userInfo:nil repeats:NO];
-(void)timerCalled
{
NSLog(@"Timer Called");
// Your Code
}
回答by gjpc
The answers are missing a specific time of day timer here is on the next hour:
答案缺少一天中特定时间的计时器,这里是下一小时:
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];
Of course, substitute "doRefresh" with your class's desired method
当然,将“doRefresh”替换为您班级所需的方法
try to create the calendar object once and make the allUnits a static for efficiency.
尝试创建一次日历对象,并将 allUnits 设为静态以提高效率。
adding one to hour component works just fine, no need for a midnight test (link)
添加一小时组件效果很好,不需要午夜测试(链接)

