UILabel updating incorrectly with NSTimer - ios

I am showing a count down timer using UILabel and NSTimer -
-(void)a_Method
{
[coolTimeLbl setNeedsDisplay];
coolTime = 5; // it is an int
coolingTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(cooling) userInfo:nil repeats:YES]; // NSTimer
}
-(void)cooling
{
if (coolTime>0)
{
coolTime = coolTime-1;
NSLog(#" coolTime----%#",coolTime);
coolTimeLbl.text =[NSString stringWithFormat:#"%d",coolTime];
NSLog(#" coolTimeLbl----%#",coolTimeLbl.text);
}
else
{
[coolingTimer invalidate];
coolingTimer = nil;
}
}
The first time everything works fine and I am getting coolTimeLbl.text as - 4 3 2 1 0
But the second time when I call aMethod, coolTimeLbl is not getting updated properly - it is like 3 2 0 etc (some weird behavior)
However both NSLogs (coolTime & coolTimeLbl) print perfectly all the times and values.
Why does this happen? I tried many ways like NSNotification etc.
Please help me to fix this.

If you're calling a_Method more than once before coolingTimer invalidates itself, the timer will tick more than once.
You should add some boolean like ;
BOOL isTimerValid;
in a_Method,
if(!isTimerValid)
{
isTimerValid = YES;
coolingTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(cooling) userInfo:nil repeats:YES]; // NSTimer
}
in cooling,
else
{
isTimerValid = NO;
....
}

Had the same issue in one of my viewControllers and another one was working OK with same NSTimer code. Looked at about 20 SO threads to get it solved. No luck. In my case
myLabel.opaque = false
solved it.
Don't ask me why.

Related

Scoring stops and resets game

I'm making a game where you are supposed to move an image between other image without colliding. Everything worked fine until I added coins to the game. When the image hits a coin, it's supposed to make a sound (which it does) and add +1 to the coin label. The problem is, when I add the code to make the coinlabel get +1, the image that I'm moving will stop and go back to starting position. The same thing happened to me when I was using an NSTimer (because users playing the app had time on finish the level.) But everytime the label counted a number, the game stopped again and the ball was put back to the starting position.
Here is some code for the game.
-(IBAction)left {
goLeft = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(goLeft) userInfo:nil repeats:YES];
if (goLeft == nil) {
goLeft = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(goLeft) userInfo:nil repeats:YES];
}
}
-(IBAction)stopLeft {
[goLeft invalidate]; goLeft = nil;
}
-(void)goLeft {
image.center = CGPointMake(image.center.x -3.5, image.center.y);
{
//Coins
if (CGRectIntersectsRect(image.frame, coin1.frame)) {
coin1.hidden = YES;
[self getcoins];
}
-(void)getcoins{
//Here i have a avaudioplayer playing a noise (dont need to show that as that works fine)
//Then the +1 to label
coinlabel.text = [[NSNumber numberWithInt:([coinlabel.text intValue] + 1)] stringValue];
// And when i add this and the image hits the coin, the image goes back to the starting position. But i want it not to stop or anything, but continue.
}
The left action is connected to touch down. And stopleft is connected to touch up inside. Hope you understand and thanks for any help.

Im trying to set up an NSTimer that is connected to an image so that it is only valid while it isn't interacting with another image

In the .h file I set up the Goodguy, Building1 and 2, the NSTimer, and the falldown method.
IBOutlet UIImageView *Goodguy;
IBOutlet UIImageView *Building1;
IBOutlet UIImageView *Building2;
NSTimer *GoodguyFall;
-(void)falldown;
In the .m file I set up the GoodguyFall NSTimer, and the code for when an image touches another image it will invalidate the NSTimer. How do I set it up so the timer is valid while it isn't touching the "buildings"?
-(void)viewDidLoad{
GoodguyFall = [ NSTimer scheduledTimerWithTimeInterval: 0.03 target:self selector:#selector(falldown) userInfo:nil repeats:YES];
}
-(void)falldown{
Goodguy.center = (CGPointMake(Goodguy.center.x, Goodguy.center.y + 6));
}
if (CGRectIntersectsRect(Goodguy.frame, Building1.frame)){
[GoodguyFall invalidate];
}
if (CGRectIntersectsRect(Goodguy.frame, Building2.frame)){
[GoodguyFall invalidate];
}
}
To get the Goodguy to fall again after not touching a building, you’ll need to schedule another timer. This can be accomplished by
-(void)BuidlingMoving{
if (CGRectIntersectsRect(Goodguy.frame, Building1.frame)){
[GoodguyFall invalidate];
GoodguyFall = nil;
}
else if (CGRectIntersectsRect(Goodguy.frame, Building2.frame)){
[GoodguyFall invalidate];
GoodguyFall = nil;
} else if (GoodguyFall == nil) {
GoodguyFall = [ NSTimer scheduledTimerWithTimeInterval: 0.03 target:self selector:#selector(falldown) userInfo:nil repeats:YES];
}
}
In this solution, I’m handling the case where Goodguy is no longer in contact with a building.

Undeclared selector warnining in ios 7

I'm tying create a welcome label using NSTimer but its showing the through some warnings
like
undeclared selector hidelable and unused variable timer
I have not used the NSTimer before can one pls tell me where im doing wrong and wt is the right method to do it.I need to give a welcome message when app load after few minities it has to disappear
i have tried this one im not able to get pls help me
this is the code i have to used in the view didload
NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:#selector(hideLabel:) userInfo:nil repeats:NO];
in storyboard i have used ib label which i want to display message
#property (strong, nonatomic) IBOutlet UILabel *wel;
please any one tell wt is proper way to make this one..
you have not declared hideLabel method.hence it gives that warning
[NSTimer scheduledTimerWithTimeInterval:60 target:self selector:#selector(hideLabel:) userInfo:nil repeats:NO];
-(void)hideLabel:(NSTimer *)timer{
myLabel.hidden=YES;
}
Try this
[NSTimer scheduledTimerWithTimeInterval:0.3 target:self selector:#selector(timerCalled) userInfo:nil repeats:YES];
-(void)timerCalled
{
NSLog(#"Timer Called...");
}
According to your code, You didn't use timer anywhere else, and didn't fire repeatedly. Then you can use this code as below..
[self performSelector:#selector(hideLabel:) withObject:yourLabel afterDelay:60];
Importantly, define your target method,
-(void)hideLabel:(UILabel*)label
{
// your code here...
label.text = #"Fired...";
}
If you does not need to use (extra use of) object of NSTimer then you should create NSTimer such like,
[NSTimer scheduledTimerWithTimeInterval:60.0f target:self selector:#selector(hideLabel:) userInfo:nil repeats:NO];
And then you need to declare timer's method other wise after active (60 sec.) timer you will be get error.
- (void)hideLabel:(NSTimer *)theTimer
{
// Timer method code;
}

When a button passes through a specified Y value, all the other buttons falling also disappear with it

I'm trying to make multiple buttons fall down the screen all at once, at different speeds. But when I have my if statement check if it passed through the value, all the other buttons disappear with it. I'm also incrementing the score to go -1 each time a button passes through the Y value. Any help is appreciated, thanks.
- (void)b1Fall
{
b1.center = CGPointMake(b1.center.x, b1.center.y+6);
if (b1.center.y >= 506) {
[self updateScore];
b1.center = CGPointMake(44, 11);
}
}
- (void)b2Fall
{
b2.center = CGPointMake(b2.center.x, b2.center.y+7);
if (b2.center.y >= 506) {
[self updateScore];
b2.center = CGPointMake(160, 11);
}
}
- (void)b3Fall
{
b3.center = CGPointMake(b3.center.x, b3.center.y+8);
if (b3.center.y >= 506) {
[self updateScore];
b3.center = CGPointMake(276, 11);
}
}
- (void)updateScore
{
healthLabel.text = [NSString stringWithFormat:#"%d", [healthLabel.text intValue]-1];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// REMOVE AFTER TESTING
b1Timer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:#selector(b1Fall) userInfo:nil repeats:true];
b2Timer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:#selector(b2Fall) userInfo:nil repeats:true];
b2Timer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:#selector(b3Fall) userInfo:nil repeats:true];
}
A few things:
1.) Put these animations in viewDidAppear instead of viewDidLoad - you want the animation to begin when the user is actually looking at the buttons, not when the view is loaded into memory, where the user may not be able to see it (viewDidLoad).
2.) Don't use NSTimer for animations, use this:
[UIView animateWithDuration:0.5
delay:1.0
options: UIViewAnimationCurveEaseOut
animations:^{
}
completion:^(BOOL finished){
// loop your animation here.
}];
3.) If you want to make a game, I don't recommend using this approach. All animations using UIKit are going to perform on the main thread and block the user flow. What you want is a framework like Cocos2D where the animations are doing in the GPU and ASYNC game logic is readily supported. UIKit isn't a good choice for game development in general.

I'm trying to make a simple loop and it crashes every time I run it

- (IBAction) goStrobe:(id) sender {
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(runLoop:)
userInfo:nil
repeats:YES];
}
- (void) runLoop {
if (imageTwo.hidden = YES) {
imageTwo.hidden = NO;
}
if (imageTwo.hidden = NO) {
imageTwo.hidden = YES;
}
}
My code is above. Every time I trigger goStrobe, it crashes and I can't figure out why. Any help would be greatly appreciated. Thanks
It's your runLoop function signature which is wrong in the selector, just remove the ":" at the end. You don't need this because your function does not take any parameters.

Resources