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

发布于 2024-10-22 07:28:24 字数 2675 浏览 2 评论 0原文

我已经研究了好几天如何做到这一点,但没有人有答案。

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

有谁知道该怎么做?

编辑2: 我的模拟器甚至不会运行该应用程序,因此我目前不知道计时器是否实际工作,但从我之前的尝试来看,它没有工作。它没有以我想要的格式显示,并且以 2 为单位倒计时(从上次实际工作时算起)。问题还在于我对 Objective-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

I have been researching for days on how to do this and nobody has an answer.

I am creating an app with 5 timers on the same view.
I need to create a timer that counts down from "15:00" (minutes and seconds), and, another that counts down from "2:58" (minutes and seconds). The 15 minute timer should not repeat, but it should stop all other timers when it reaches "00:00." The "2:58" timer should repeat until the "15:00" or "Game Clock" reaches 0. Right now, I have scrapped almost all of my code and I'm working on the "2:58" repeating timer, or "rocketTimer."

Does anyone know how to do this?

EDIT 2:
My simulator will not even run the app so I currently have no idea if the timer is actually working or not, but from my previous attempts, it has not worked. It doesn't show up in the format that I want and it counts down by 2's (from the last time it actually worked). The problem is, also, that I'm not fluent in objective-C. I can write pseudocode all day, just like everyone else, but I cannot put what I want into code because I do not fully understand the NSTimer.

EDIT:

In my output, I get this error "terminate called after throwing an instance of 'NSException'"

and this error?

my error

Here is my code:

    #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

and my .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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

相守太难 2024-10-29 07:28:24

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

第一个也是最明显的问题

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

Start 中安排计时器后,您的 timerLoop: 方法将每秒调用一次。但是您忘记检查 totalSeconds 是否已变为负数...

第二个问题

-(NSString *)timeFormatted:(int)newTotalSeconds 不会按您期望的方式工作!实际上,我非常确定 Xcode 会向您发出编译器警告,指出“‘newTotalSeconds’的本地声明隐藏了实例变量”
尝试一下:在 Start 中,将行 rocketCount.text = [self timeFormatted:newTotalSeconds]; 替换为行 rocketCount.text = [self timeFormatted:42 ]; 并在其后设置断点。

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

您的dealloc完全错误:
首先也是最重要的是,在 [super dealloc] 之后进行任何调用并不是最好的主意。其次,“你做错了”:考虑到你的Start方法,你不拥有计时器,所以你不能释放它。相反,如果计时器仍然有效,您需要将其无效。但这甚至不会成为问题,因为只要安排了rocketTimer,您的viewController就不会被dealloc(除非您有其他地方的内存管理中的错误)。我写了一个相当完整的示例在之前的文章中解释了这种行为。

那么,是什么原因导致了这次事故呢?

老实说:
没有线索!

为了找出到底出了什么问题,请尝试向 -[NSException raise] 添加断点。或者,您可以将 main.m 中的 main 函数修改为以下内容:

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;
}

这将告诉您程序实际上是在哪个方法中崩溃的。

There are a few problems with your code!
The bad news is, that none of them relate to the crash you are seeing.

The first and most obvious problem

Actually, you never stop your countdown!

After you've scheduled the timer in Start, your timerLoop:-method will be called every second. But you forgot to check whether totalSeconds has become negative...

The second problem

-(NSString *)timeFormatted:(int)newTotalSeconds will not work the way you expect it to! Actually, I'm pretty damn sure that Xcode gives you a compiler warning stating "Local declaration of 'newTotalSeconds' hides instance variable".
Try it out: In Start, replace the line rocketCount.text = [self timeFormatted:newTotalSeconds]; with the line rocketCount.text = [self timeFormatted:42]; and set a breakpoint after it.

The third problem (which actually are a couple of problems in one place)

Your dealloc is plain wrong:
First and foremost, it's not the best idea to have any calls after [super dealloc]. Second, "ur doin it wrong": Considering your Start-method, you don't own the timer so you must not release it. Instead, if the timer was still valid, you'd need to invalidate it. But this won't even become a problem, because as long as rocketTimer is scheduled, your viewController will not be dealloced (unless you have an error within your memory-management elsewhere). I've written a fairly complete example explaining this behavior in an earlier post.

So, what caused the crash?

Honestly:
No clue!

In order to find out what exactly went wrong, try adding a breakpoint to -[NSException raise]. Alternatively, you can modify the main function in main.m to be the following:

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;
}

That will tell you in which method your program actually crashed.

南…巷孤猫 2024-10-29 07:28:24

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
// ...

Where is rocketTimer instantiated? You seem to have left that very important detail out. My guess is that rocketTimer isn't being correctly retained by your code and that is causing your crash when trying to access that object after it has been deallocated.

I'd suggest synthesizing your property and then using the built-in setting by setting self.rocketTimer when you initialize.

FirstViewController.h

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

FirstViewController.m

@implementation FirstViewController
@synthesize rocketTimer;
// test of implementation
// ...
朮生 2024-10-29 07:28:24

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

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

If the problem is that it's not repeating, i'd let the timerLoop method check the value of totalSeconds before substracting. If it's 0, let it set it to 178 again.

If the problem lies somewhere else, please tell us where, and give us a little more information on what the problem is and what you've tried already next time.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文