NSTimer在课堂上

时间:2012-02-12 12:53:44

标签: objective-c xcode cocoa-touch nstimer

我有一个定时器类设置,基本上处理所有倒计时器逻辑。所有这一切都是按下按钮 - 从60到0秒计数。

我在Timer.m类中有以下代码。

- (void)advanceTimer
{
    self.lengthOfTime = [NSNumber numberWithInt:self.lengthOfTime.intValue - 1];
    NSLog(@"%@",self.lengthOfTime);
    [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(advanceTimer) userInfo:nil repeats:NO];
}
- (void)startCountdown
{
    if (!self.lengthOfTime) self.lengthOfTime = [NSNumber numberWithInt:60];
    [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(advanceTimer) userInfo:nil repeats:NO];
}

我要做的是在我的View Controller中创建一个计时器对象,它将从ViewController.m更新标签。目前 - 该类正常工作,因为我可以从Timer类中进行NSLog,并且它可以正确倒计时。我想过让advanceTimer方法返回 - 但我似乎无法理解如何使用返回的数据更新ViewController中的标签。

冷却让回归工作的唯一方法就是让按钮将标签刷新到正确的倒计时时间......我无法让它自动倒计时......

3 个答案:

答案 0 :(得分:1)

如果我错了,请纠正我,但我认为你应该在班级成员中保留NSTimer。否则,在完成方法时会破坏计时器。

@property (nonatomic,retain) NSTimer * yourTimer;

在.m文件中

@synthesize yourTimer;

然后

- (void)advanceTimer
{
self.lengthOfTime = [NSNumber numberWithInt:self.lengthOfTime.intValue - 1];
NSLog(@"%@",self.lengthOfTime);
self.yourTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(advanceTimer)     userInfo:nil repeats:NO];
}
- (void)startCountdown
{
if (!self.lengthOfTime) self.lengthOfTime = [NSNumber numberWithInt:60];
self.yourTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(advanceTimer) userInfo:nil repeats:NO];
}

我还修复了你的NSNumber alloc,所以没有内存泄漏;) 解释它,NSTimer scheduledTimerWithTimeInterval:给你一个自动释放的NSTimer。如果某个成员没有保留此Timer,则只要方法结​​束就会释放它,并且由于没有其他指针保留它,它将被释放。也许这就是解释;)。从未与NSTimers合作

答案 1 :(得分:1)

倒计时类需要将链接保存回ViewController,然后在其上调用方法。

一种方法是使用委托模式。将Countdown类的init方法设为initWithDelegate:(id)delegate,并使用预定义的回调方法(如updateCountdown:(NSNumber*)currentCountdown)。 ViewController将自己作为委托发送并实现更新方法。

另一种方法是目标/行动模式。 NSTimer使用这种方法。 init方法是initWithTarget:(id)target selector:(SEL)selector。 ViewController将自己作为目标和它想要使用的任何选择器发送(只要它将NSNumber作为唯一的参数)。

advanceTimer中的两种情况下,Countdown类将使用performSelector:withObject:来调用ViewController的更新方法。

如果你真的想要一个真正的一秒计时器,那么将它设置为重复。否则,您将慢慢漂移advanceTimer方法触发和完成所需的时间。在倒计时结束时,使用对计时器的引用使其无效。

答案 2 :(得分:1)

好吧,如果您知道如何通过单击按钮更新标签,那么您已准备好连接其他所有内容的所有内容:

如果您的视图控制器有标签的IBOutlet和更新它的IBAction,为什么不在advanceTimer方法中调用视图控制器的操作?

更简单,您可以将计时器类连接到标签。 你可以这样做:

// Timer.h:
@interface Timer : NSObject

@property (retain, nonatomic) IBOutlet UILabel *timeLabel;
@property (assign, nonatomic) NSInteger secondsRemaining;
@property (assign, nonatomic) NSTimer *timer;

- (IBAction)startCountdown:(id)sender;
- (IBAction)stopCountdown:(id)sender;
- (void)timerFired:(NSTimer *)timer;

@end

// Timer.m
@implementation Timer

@synthesize timeLabel = timeLabel_;
@synthesize secondsRemaining = secondsRemaining;
@synthesize timer = timer_;

- (void)setTimer:(NSTimer *)timer
{
    if (timer = timer_)
        return;

    [timer_ invalidate];
    timer_ = timer;
}

- (void)scheduleTimer
{
    if (self.secondsRemaining <= 0) {
        self.timer = nil;
    } else {
        self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerFired:) userInfo:nil repeats:NO];
    }
}

- (void)timerFired:(NSTimer *)timer
{
    self.secondsRemaining -= 1;
    NSString *displayString = [NSString stringWithFormat:@"%d", self.secondsRemaining];
    self.timeLabel.text = displayString;
    [self scheduleTimer];
}

- (IBAction)startCountdown:(id)sender
{
    self.secondsRemaining = 60;
    [self scheduleTimer];
}

- (IBAction)stopCountdown:(id)sender
{
    self.timer = nil;
}

- (void)dealloc
{
    [timeLabel_ release];
    [super dealloc];
}

@end

此代码有两个好处:

  • 您可以取消计时器。
  • 您的视图控制器无需了解任何相关信息 - 您可以完全在界面构建器中进行设置。
相关问题