xcode NSTimer 问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3220695/
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
NSTimer problem
提问by Roosh
So I am trying to set up a basic timer but I am failing miserably. Basically all I want is to start a 60 second timer when the user clicks a button, and to update a label with the time remaining(like a countdown). I created my label and button and connected them in IB. Next I created a IBAction for the button. Now when I tried to update the label based on the timer, my app screws up. Here's my code:
所以我试图设置一个基本的计时器,但我失败了。基本上我想要的只是在用户单击按钮时启动 60 秒计时器,并使用剩余时间更新标签(如倒计时)。我创建了我的标签和按钮,并在 IB 中将它们连接起来。接下来我为按钮创建了一个 IBAction。现在,当我尝试根据计时器更新标签时,我的应用程序出错了。这是我的代码:
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 1
target: self
selector:@selector(updateLabelDisplay)
userInfo: nil repeats:YES];
I also have an updateLabelDisplay function that determines how many times the timer has ran and then subtracted that number from 60 and displays that number in the countdown label. Can anyone tell me what I am doing wrong?
我还有一个 updateLabelDisplay 函数,用于确定计时器运行了多少次,然后从 60 中减去该数字并在倒计时标签中显示该数字。谁能告诉我我做错了什么?
回答by Darryl H. Thomas
Ok, well for starters, check this out if you haven't already: Official Apple Docs about Using Timers
好的,对于初学者来说,如果您还没有的话,请检查一下:关于使用计时器的 Apple 官方文档
Based on your description, you probably want code that looks something like this. I've made some assumptions regarding behavior, but you can suit to taste.
根据您的描述,您可能需要看起来像这样的代码。我对行为做了一些假设,但你可以适应。
This example assumes that you want to hold on to a reference to the timer so that you could pause it or something. If this is not the case, you could modify the handleTimerTick method so that it takes an NSTimer* as an argument and use this for invalidating the timer once it has expired.
这个例子假设你想保持对计时器的引用,以便你可以暂停它或其他东西。如果不是这种情况,您可以修改 handleTimerTick 方法,使其接受 NSTimer* 作为参数,并在计时器过期后使用它来使计时器失效。
@interface MyController : UIViewController
{
UILabel * theLabel;
@private
NSTimer * countdownTimer;
NSUInteger remainingTicks;
}
@property (nonatomic, retain) IBOutlet UILabel * theLabel;
-(IBAction)doCountdown: (id)sender;
-(void)handleTimerTick;
-(void)updateLabel;
@end
@implementation MyController
@synthesize theLabel;
// { your own lifecycle code here.... }
-(IBAction)doCountdown: (id)sender
{
if (countdownTimer)
return;
remainingTicks = 60;
[self updateLabel];
countdownTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target: self selector: @selector(handleTimerTick) userInfo: nil repeats: YES];
}
-(void)handleTimerTick
{
remainingTicks--;
[self updateLabel];
if (remainingTicks <= 0) {
[countdownTimer invalidate];
countdownTimer = nil;
}
}
-(void)updateLabel
{
theLabel.text = [[NSNumber numberWithUnsignedInt: remainingTicks] stringValue];
}
@end
回答by SK9
It may be a little late to post a second answer to this question but I've been looking for a good place to post my own solution to this problem. In case it is of use to anyone here it is. It fires 8 times but of course this can be customised as you please. The timer deallocates itself when time is up.
发布这个问题的第二个答案可能有点晚了,但我一直在寻找一个好地方来发布我自己的解决方案。如果它对这里的任何人有用。它会发射 8 次,但当然可以根据需要进行自定义。当时间到时,计时器会自行解除分配。
I like this approach because it keeps the counter integrated with the timer.
我喜欢这种方法,因为它使计数器与计时器保持集成。
To create an instance call something like:
要创建一个实例调用类似:
SpecialKTimer *timer = [[SpecialKTimer alloc] initWithTimeInterval:0.1
andTarget:myObject
andSelector:@selector(methodInMyObjectForTimer)];
Anyway, here are the header and method files.
不管怎样,这里是头文件和方法文件。
//Header
#import <Foundation/Foundation.h>
@interface SpecialKTimer : NSObject {
@private
NSTimer *timer;
id target;
SEL selector;
unsigned int counter;
}
- (id)initWithTimeInterval:(NSTimeInterval)seconds
andTarget:(id)t
andSelector:(SEL)s;
- (void)dealloc;
@end
//Implementation
#import "SpecialKTimer.h"
@interface SpecialKTimer()
- (void)resetCounter;
- (void)incrementCounter;
- (void)targetMethod;
@end
@implementation SpecialKTimer
- (id)initWithTimeInterval:(NSTimeInterval)seconds
andTarget:(id)t
andSelector:(SEL)s {
if ( self == [super init] ) {
[self resetCounter];
target = t;
selector = s;
timer = [NSTimer scheduledTimerWithTimeInterval:seconds
target:self
selector:@selector(targetMethod)
userInfo:nil
repeats:YES];
}
return self;
}
- (void)resetCounter {
counter = 0;
}
- (void)incrementCounter {
counter++;
}
- (void)targetMethod {
if ( counter < 8 ) {
IMP methodPointer = [target methodForSelector:selector];
methodPointer(target, selector);
[self incrementCounter];
}
else {
[timer invalidate];
[self release];
}
}
- (void)dealloc {
[super dealloc];
}
@end