倒计时器

问题描述 投票:0回答:3

我正在尝试创建一个倒计时器,它是一个连接到文本字段的 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];
}
objective-c cocoa
3个回答
19
投票

到目前为止,您走在正确的道路上。

坚持使用已有的代码,以下是

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 定义中的拼写错误...导致恼人的“无法识别的选择器发送到实例”异常


6
投票

您可以添加一个实例变量 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];
}

0
投票

看起来您走在正确的轨道上,但您需要进行一些调整才能实现倒计时器功能。我将逐步指导您完成整个过程。

首先解答一下大家的疑问:

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 正确连接。

© www.soinside.com 2019 - 2024. All rights reserved.