我正在尝试创建一个倒计时器,它是一个连接到文本字段的 IBOutlet,从 60 秒倒计时到 0。我不确定
A.如何将重复次数限制为 60 和
B.如何提前递减倒计时定时器:
- (IBAction)startCountdown:(id)sender
{
NSTimer *countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(advanceTimer:) userInfo:nil repeats:YES];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:countdownTimer forMode:NSDefaultRunLoopMode];
}
- (void)advanceTimer:(NSTimer *)timer
{
[countdown setIntegerValue:59];
}
到目前为止,您走在正确的道路上。
坚持使用已有的代码,以下是
advanceTimer
方法应如何使其工作:
- (void)advanceTimer:(NSTimer *)timer
{
[countdown setIntegerValue:([countdown integerValue] - 1)];
if ([countdown integerValue] == 0)
{
// code to stop the timer
}
}
编辑: 为了使整个事情更加面向对象,并避免每次都从字符串到数字来回转换,我会这样做:
// Controller.h:
@interface Controller
{
int counter;
IBOutlet NSTextField * countdownField;
}
@property (assign) int counter;
- (IBAction)startCountdown:(id)sender;
@end
// Controller.m:
@implementation Controller
- (IBAction)startCountdown:(id)sender
{
counter = 60;
NSTimer *countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:@selector(advanceTimer:)
userInfo:nil
repeats:YES];
}
- (void)advanceTimer:(NSTimer *)timer
{
[self setCounter:(counter -1)];
[countdownField setIntegerValue:counter];
if (counter <= 0) { [timer invalidate]; }
}
@end
并且,如果您可以使用绑定,则可以简单地将文本字段的
intValue
绑定到 counter
的 Controller
属性。这将允许您消除类界面中的 IBOutlet
以及 setIntegerValue:
中的 advanceTimer
行。
更新:删除了将计时器添加到运行循环两次的代码。感谢 Nikolai Ruhe 和 nschmidt 注意到这个错误。
更新: 根据 nschmidt 使用
setIntegerValue
方法来简化代码。
编辑: (void)advanceTimer:(NSTimer *)timer 定义中的拼写错误...导致恼人的“无法识别的选择器发送到实例”异常
您可以添加一个实例变量 int _timerValue 来保存计时器值,然后执行以下操作。另请注意,您正在创建的 NSTimer 已安排在当前运行循环上。
- (IBAction)startCountdown:(id)sender
{
_timerValue = 60;
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(advanceTimer:) userInfo:nil repeats:NO];
}
- (void)advanceTimer:(NSTimer *)timer
{
--_timerValue;
if(self.timerValue != 0)
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(advanceTimer:) userInfo:nil repeats:NO];
[countdown setIntegerValue:_timerValue];
}
看起来您走在正确的轨道上,但您需要进行一些调整才能实现倒计时器功能。我将逐步指导您完成整个过程。
首先解答一下大家的疑问:
A.如何将重复次数限制为 60: 您希望倒计时从 60 秒开始并减少到 0,因此您实际上不需要将重复次数限制为 60。相反,您需要跟踪剩余秒数并在计时器到达时停止计时器。达到0.
B.如何提前递减倒计时定时器: 在 advanceTimer: 方法中,每次计时器触发时,您应该将倒计时值减 1。此外,您需要更新用户界面 (UI) 以反映新的倒计时值。您似乎正在使用名为倒计时的文本字段来显示倒计时值。
以下是修改代码以实现目标的方法:
@interface YourViewController ()
@property (nonatomic, strong) NSTimer *countdownTimer;
@property (nonatomic) NSInteger countdownValue;
@end
@implementation YourViewController
- (IBAction)startCountdown:(id)sender
{
self.countdownValue = 60; // Start countdown from 60 seconds
[self updateCountdownUI]; // Update the UI initially
// Invalidate any existing timer before starting a new one
[self.countdownTimer invalidate];
self.countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(advanceTimer:) userInfo:nil repeats:YES];
}
- (void)advanceTimer:(NSTimer *)timer
{
if (self.countdownValue > 0) {
self.countdownValue -= 1; // Decrement countdown value
[self updateCountdownUI]; // Update the UI
if (self.countdownValue == 0) {
[self.countdownTimer invalidate]; // Stop the timer when countdown reaches 0
}
}
}
- (void)updateCountdownUI
{
// Update your countdown text field with the current countdown value
[countdown setIntegerValue:self.countdownValue];
}
@end
在此代码中,countdownValue 属性用于跟踪剩余时间。 updateCountdownUI 方法负责使用新的倒计时值更新 UI。 advanceTimer: 方法减少倒计时值并相应地更新 UI。当倒计时达到0时计时器失效。
记住将 YourViewController 替换为视图控制器类的实际名称,并确保倒计时文本字段的 IBOutlet 正确连接。