倒数计时器使用“0:00”格式的NSTimer

时间:2011-03-18 00:10:15

标签: objective-c cocoa-touch nstimer countdown

我一直在研究如何做到这一点,没有人有答案。

我正在同一个视图上创建一个包含5个定时器的应用。 我需要创建一个从“15:00”(分钟和秒)倒计时的计时器,另一个从“2:58”(分钟和秒)倒计时的计时器。 15分钟的计时器不应该重复,但它应该在到达“00:00”时停止所有其他计时器。 “2:58”计时器应该重复,直到“15:00”或“游戏时钟”达到0.现在,我已经废弃了几乎所有的代码,我正在研究“2:58”重复计时器,或“rocketTimer。”

有谁知道怎么做?

编辑2: 我的模拟器甚至不会运行应用程序,所以我目前不知道计时器是否实际工作,但从我以前的尝试,它没有工作。它没有以我想要的格式显示,并且按2(从上次实际工作时间)开始倒计时。问题是,我不能说客观C语言。我可以像其他人一样整天写伪代码,但是我不能把我想要的东西放到代码中,因为我不完全理解NSTimer。

编辑:

在我的输出中,我收到此错误“在抛出'NSException'实例后调用终止”

和这个错误?

my error

这是我的代码:

    #import <UIKit/UIKit.h>


@interface FirstViewController : UIViewController {



    //Rocket Timer
    int totalSeconds;
    bool timerActive;
    NSTimer *rocketTimer;
    IBOutlet UILabel *rocketCount;

    int newTotalSeconds;
    int totalRocketSeconds;
    int minutes;
    int seconds;

}

- (IBAction)Start;



@end

和我的.m

    #import "FirstViewController.h"

@implementation FirstViewController

- (NSString *)timeFormatted:(int)newTotalSeconds
{

    int seconds = totalSeconds % 60; 
    int minutes = (totalSeconds / 60) % 60; 


    return [NSString stringWithFormat:@"%i:%02d"], minutes, seconds; 
}


-(IBAction)Start {

    newTotalSeconds = 178; //for 2:58

    newTotalSeconds = newTotalSeconds-1;

    rocketCount.text = [self timeFormatted:newTotalSeconds];


    if(timerActive == NO){

        timerActive = YES;
        newTotalSeconds = 178;

      [rocketTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerLoop) userInfo:nil repeats:YES];
    }

    else{

        timerActive = NO;
        [rocketTimer invalidate];
        rocketTimer = nil;

    }

}



-(void)timerLoop:(id)sender {

    totalSeconds = totalSeconds-1;

    rocketCount.text = [self timeFormatted:totalSeconds];


}

- (void)dealloc
{
    [super dealloc];

    [rocketTimer release];


}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}


- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    timerActive = NO;
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

@end

3 个答案:

答案 0 :(得分:3)

您的代码存在一些问题!
坏消息是,它们都与您所看到的崩溃无关。

第一个也是最明显的问题

实际上,你永远不会停止倒计时!

Start中安排计时器后,您的timerLoop: - 方法将每秒调用一次。但你忘了检查totalSeconds是否已成为否定......

第二个问题

-(NSString *)timeFormatted:(int)newTotalSeconds将无法按照您的预期运作!实际上,我非常确定Xcode会给你一个编译器警告,说明“newTotalSeconds的本地声明”隐藏实例变量“
试一试:在Start中,将行rocketCount.text = [self timeFormatted:newTotalSeconds];替换为行rocketCount.text = [self timeFormatted:42];并在其后设置断点。

第三个问题(实际上是一个地方的几个问题)

您的dealloc是完全错误的:
首先,在[super dealloc]之后进行任何调用并不是最好的主意。其次,“你做错了”:考虑到你的Start方法,你不拥有计时器,所以你不能 release它。相反,如果计时器仍然有效,则需要invalidate它。但这甚至不会成为问题,因为只要安排了rocketTimer,你的viewController就不会被dealloc编辑(除非你的记忆中有错误 - 管理其他地方)。我在之前的帖子中写了fairly complete example来解释这种行为。

那么,是什么导致了崩溃?

坦白:
不知道!

为了找出确切出错的地方,请尝试向-[NSException raise]添加断点。或者,您可以将main中的main.m功能修改为以下内容:

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    int response;
    @try {
        response = UIApplicationMain(argc, argv, nil, nil);
    } @catch (NSException *e) {
        NSLog(@"%@: %@\nCall-stack:\n%@", [e name], [e reason], [e callStackSymbols]);
        response = 1;
    }
    return response;
}

这会告诉你程序实际崩溃的方法。

答案 1 :(得分:1)

rocketTimer在哪里实例化?你似乎已经离开了那个非常重要的细节。我的猜测是,rocketTimer未被您的代码正确保留,并且在解除分配后尝试访问该对象时导致崩溃。

我建议您在初始化时设置self.rocketTimer来合成属性,然后使用内置设置。

FirstViewController.h

@interface FirstViewController : UIViewController {
    NSTimer *rocketTimer;
}
@property (nonatomic, retain) NSTimer *rocketTimer;
- (IBAction)Start;
@end

FirstViewController.m

@implementation FirstViewController
@synthesize rocketTimer;
// test of implementation
// ...

答案 2 :(得分:0)

如果问题是它没有重复,我会让timerLoop方法在减去之前检查totalSeconds的值。如果为0,则将其再次设置为178。

如果问题出在其他地方,请告诉我们在哪里,并向我们提供一些有关问题的详细信息以及您下次已经尝试过的问题。