Timer label isn't counting down - objective-c

This is not all the code. I have made sure that I have declared everything correctly however the label is not changing as 'seconds' is decreasing.
I'm not sure why as in 'subtractTime' I have made timerLabel.text equal to the string with format using seconds which "should" and is counting down as I use an alert to reset the game and so even though the label isn't changing, I know it is counting down otherwise the alert wouldn't be triggered from 'seconds' equalling 0.
- (void)setupGame;
{
seconds = 30;
count = 0;
timerLabel.text = [NSString stringWithFormat: #"Time: %i", seconds];
scoreLabel.text = [NSString stringWithFormat: #"Score: %i", count];
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(subtractTime)
userInfo:nil
repeats:YES];
}
- (void)subtractTime;
{
seconds--;
timerLabel.text = [NSString stringWithFormat:#"Time: %i", seconds];
if (seconds == 0)
{
[timer invalidate];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: #"Time is up !"
message: [NSString stringWithFormat: #"You Scored %i points", count]
delegate:self
cancelButtonTitle: #"Play Again"
otherButtonTitles:nil];
[alert show];
}
}
#end

Make sure in Storyboard/Interface builder that your label is wired properly to the viewXontroller's .h file. A good way to test this is to "prime" your label on the XIB with something other than "Time:" but instead with something nonsensical like "foo". That way you'll be able to accurately tell if the label is changing at all versus troubleshooting whether or not your Int value isn't showing properly.

Related

Objective-C code hang

I have a tap counter and this is the "Who Wins" code. The app is crashing whenever Flipped (int timer) is equal to 30 and it is deciding who had the most taps. It always says "Player 2 Wins" and freezes. Please help. Number is the number value of one tapper, Number1 is the value of the second tapper. How do I fix this?
- (void)countup
{
if (Fliped == 30)
{
//error message
if (Number < Number1)
{
myAlertView = [[UIAlertView alloc] initWithTitle:#"Stop!" message:#"Player 2 Wins!" delegate:self
cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
timer = [NSTimer scheduledTimerWithTimeInterval:0.0
target:self selector:#selector(countup)userInfo:nil repeats:YES];
[myAlertView show];
}
if (Number > Number1)
{
myAlertView = [[UIAlertView alloc] initWithTitle:#"Stop!" message:#"Player 1 Wins!" delegate:self
cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
timer = [NSTimer scheduledTimerWithTimeInterval:0.0
target:self selector:#selector(countup)userInfo:nil repeats:YES];
[myAlertView show];
}
else
{
MainInt += 1;
seconds.text = [NSString stringWithFormat:#"%d", MainInt];
Fliped += 1;
secondsFlip.text = [NSString stringWithFormat:#"%d", Fliped];
}
}
Thanks in advance.
what could be the cause of this crash???
You're calling your own method countup recursively an infinite number of times when the variable Fliped is 30. That's why you're crashing. Don't do that.

How can I change the value of an NSString every N seconds using?

I have this code to change the number in the NSString every five seconds.
How will I keep the numbers running in a loop? It now runs from 1 to 19 ,and stops at the last one (19) with a SIGABRT on the line: label.text = ...
How can I start with the first number displayed (0), before the first timer fires?
Here is the code:
-(IBAction) rotate3
{
NSString *number = [self.dayArray description];
NSArray *array = [[NSArray alloc] initWithObjects: #"0", #"1", #"2",..., #"19",nil];
number = #"0" ;
numberCount++ ;
self.dayArray = array;
[array release];
label.text = [NSString stringWithFormat:#"Day: %# ", [dayArray objectAtIndex :numberCount ]];
}
//and the timer
- (void)viewDidLoad
{
timer=[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(rotate3 )userInfo:nil repeats:YES];
}
Here is my answers:
1)I think, at the last one (19), the numberCount is 20 (numberCount++ ;).
2)Just set the value before scheduling the timer.
add this to your .h file, in your interface (that is, if it isn't already there)
{
NSInteger numberCount
}
Then in your viewDidLoad method, initialize numberCount and the label:
numberCount = 0;
label.text = #"0";
And in your time method, replace:
numberCount++
with
if(numberCount++ > 19)
numberCount = 0;
What is the "number" NSString used for, b.t.w.?
Why have dayArray?
why not something like
label.text = [NSString stringWithFormat:#"Day: %d", numberCount++];
if (numberCount>19) numberCount = 0;
I don't know what you have number count initialized to it should probably be -1 and also reinitialized to -1 . if you wish to iterate thru "Day: 0" ... "Day: 19"
It's not clear.
You could change the -(void)viewDidLoad timer to not repeat
timer=[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(rotate3 )userInfo:nil repeats:NO];
then, conditionally set it up again in the rotate3 method if you still want to change the text 5 seconds later.
try this:
#pragma mark - timer callback
-(IBAction)rotate3
{
[label1 setText:[dayArray objectAtIndex:numberCount]];
numberCount++;
if (numberCount >= [dayArray count])
numberCount = 0;
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
dayArray = [[NSArray alloc] initWithObjects:#"0",#"1",#"2",#"3", nil];
[label1 setText:[dayArray objectAtIndex:0]];
numberCount = 1;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(rotate3) userInfo:nil repeats:YES];
// Do any additional setup after loading the view, typically from a nib.
}

Loop the code in #implementation section

I have written the program, which chooses a random element from the array.
Once I press the button "Start", how do I loop that code?
I would like, that once a button "Start" is pressed, a new element from the array is chosen and written in the text field every 5 seconds.... Thanks for the answer.
#implementation MARandom
- (IBAction)Start:(id)sender {
NSArray *tones;
tones = [NSArray arrayWithObjects: #"F#0", #"Gb0", #"G0", #"G#0",#"Ab0",#"A0",#"A#0",#"Bb0",#"B0",
#"C1",#"C#1",#"Db1",#"D1",#"D#1",#"Eb1",#"E1",#"F1",#"F#1",#"Gb1",#"G1",#"G#1",#"Ab1",#"A1",#"A#1",#"Bb1",#"B1",
#"C2",#"C#2",#"Db2",#"D2",#"D#2",#"Eb2",#"E2",#"F2",#"F#2",#"Gb2",#"G2",#"G#2",#"Ab2",#"A2",#"A#2",#"Bb2",#"B2",
#"C3",#"C#3",#"Db3",#"D3",#"D#3",#"Eb3",nil];
i= (arc4random() % 48);
NSString *Tone;
Tone = [tones objectAtIndex: i];
[TextField setStringValue:(NSString *)Tone];
}
Please try this:
- (IBAction)Start:(id)sender {
[NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:#selector(updateTextFieldWithRandomNumber)
userInfo:nil
repeats:YES];
}
-(void)updateTextFieldWithRandomNumber{
NSArray *tones;
tones = [NSArray arrayWithObjects: #"F#0", #"Gb0", #"G0", #"G#0",#"Ab0",#"A0",#"A#0",#"Bb0",#"B0",
#"C1",#"C#1",#"Db1",#"D1",#"D#1",#"Eb1",#"E1",#"F1",#"F#1",#"Gb1",#"G1",#"G#1",#"Ab1",#"A1",#"A#1",#"Bb1",#"B1",
#"C2",#"C#2",#"Db2",#"D2",#"D#2",#"Eb2",#"E2",#"F2",#"F#2",#"Gb2",#"G2",#"G#2",#"Ab2",#"A2",#"A#2",#"Bb2",#"B2",
#"C3",#"C#3",#"Db3",#"D3",#"D#3",#"Eb3",nil];
i= (arc4random() % 48);
NSString *Tone;
Tone = [tones objectAtIndex: i];
[TextField setStringValue:(NSString *)Tone];
}
and also consider preparing the array at one place rather than the code that will be repeatedly called, perhaps at viewDidLoad.
Note: untested code, but should work.

Comparing dates inside a nstimer selector

I am writing a countdowtimer application like the timer tab in the clock app of the iPhone. Right now I am having trouble comparing to dates, the 'now' and 'futureDate'.
all the variables are synthesized and are nonatomic and retain.
I have this code right now.
- (IBAction)startTimer:(id)sender {
NSLog(#"startTimer");
pickerView.hidden = YES;
labelView.hidden = NO;
now = [[NSDate alloc] init];
futureDate = [[NSDate alloc] initWithTimeInterval:picker.countDownDuration sinceDate:now];
NSLog(#"Dates.\nNow = (%#) \nfutureDate (%#)", now, futureDate);
timerLabelUpdater = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(labelUpdater) userInfo:nil repeats:YES];
}
- (void)labelUpdater {
if ([now timeIntervalSinceDate:futureDate] < 0.0) {
NSLog(#"YES\nDates.\nNow = (%#) \nfutureDate (%#)", now, futureDate);
} else {
NSLog(#"NO\nNow = (%#) \nfutureDate (%#)", now, futureDate);
}
}
Debugger info:
2011-02-08 16:46:02.449 App[22504:207] startTimer
2011-02-08 16:46:02.451 App[22504:207] Dates.
Now = (2011-02-08 18:46:02 +0000)
futureDate (2011-02-08 18:47:02 +0000)
2011-02-08 16:46:03.451 App[22504:207] YES
And it stay giving me yes "forever".
But if you see the variable hours, they are +2h in the future compared from my clock time. Is this the bug?
Sorry my if was testing the wrong date, comparing the variable now and futureDate the time interval will be the same forever. I replaced the now variable for a [[NSDate alloc] init] in the test. Right now the code works.
if ([[[NSDate alloc]init] timeIntervalSinceDate:futureDate] < 0.0) {
NSLog(#"YES\nDates.\nNow = (%#) \nfutureDate (%#)", now, futureDate);
} else {
NSLog(#"NO\nNow = (%#) \nfutureDate (%#)", now, futureDate);
}
sorry for the stupid question.

malloc error and simulator crash

I constantly get malloc error : double freed....
The echoTime function is being called by a button. When I press the button again before the timer ends it gives me the malloc error. When I press the button after the timer finished to start it again, the simulator hangs.
Does anyone know what is wrong with the following piece of code:
-(IBAction)echoTime: (id) sender {
if (gameTimer != nil) {
[gameTimer invalidate];
[gameTimer release];
}
NSInteger secs = 1 * 60;
if (secs != 0) {
NSNumber *elapsedSeconds = [[NSNumber alloc] initWithInt:secs];
NSDictionary *myDict = [NSDictionary dictionaryWithObject:elapsedSeconds forKey:#"TotalSeconds"];
gameTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(echoIt:) userInfo:myDict repeats: YES];
}
}
-(void)echoIt: (NSTimer *) timer {
NSNumber *num = (NSNumber *) [[timer userInfo] valueForKey:#"TotalSeconds"];
seconds++;
NSInteger sec = [num integerValue] - seconds;
NSInteger minutes = sec / 60;
[gameTimeLabel setText:[NSString stringWithFormat:#"%02i:%02i", minutes, sec-(60*minutes)]];
if (sec == 0) {
[self playSound:#"Horn"];
[gameTimer invalidate];
}
}
NSNumber *elapsedSeconds = [[NSNumber alloc] initWithInt:secs];
In general dont alloc NSNumbers and a NSDictionary (and NSArray,NSSet) always retains the objects it is given (and releases them too when it should).
try...
NSNumber *elapsedSeconds = [NSNumber numberWithInt:secs];
It'll stop the retain cycle you've got and might stop the crash.
Also irrelevant but stylewise.
NSInteger secs = [[[timer userInfo] valueForKey:#"TotalSeconds"] intValue];
Is a little more efficient.