NSTimer is not getting stopped - iphone

I am trying to stop the timer. My problem is when I try to stop the timer the value of timer is nil and it is not getting invalidated. if there any way to stop the timer except this ?
My code is like
timer is defined in header file - and also synthesized.
if([str_Message isEqualToString:ON] // if the command to start timer
{
if(!timer)
{
tmr_CallWebService = [[NSTimer scheduledTimerWithTimeInterval:Time_TracingInterval target:ClassTracing selector:#selector(startLocationTracing) userInfo:nil repeats:YES]retain];
}
//to stop timer
else if([str_Message isEqualToString:OFF])
{
if(timer)
{
[timer invalidate];
timer = nil;
}
Please help me out... thanks in advance

I think you just need to replace tmr_CallWebService with timer.

[str_Message isEqualToString:ON] should be like this [str_Message isEqualToString:#"ON"]. similarly for the comparison with OFF. Use #"OFF".

If you've got a property declared for the timer, you should use it. For instance, if your timer is defined as #property (nonatomic, retain) NSTimer *myTimer; you should refer to it as self.myTimer and set it using that setter and invalidate it later using the accessor.
It looks like you're not setting tmr_CallWebService to your timer ivar at any place so you're just leaking and losing the reference.

Related

objective-c: Animate button before timer ends

I'm working on a very simple iPhone game that involves choosing the right colored button as many times in a row based on a randomized voice prompt. I have it set up so that if the button is one color and gets clicked, it always goes to a hard-coded color every time (e.g. if you click red, it always turns blue). The color change method is set up in an IBOutlet. I have a timer set up in a while loop, and when the timer ends it checks if the player made the right selection. The problem is that the button color change does not occur until after the timer runs out, and this causes a problem with the method used to check the correct answer. Is there a way to make this color change happen instantly? From what I've searched I know it has something to do with storyboard actions not occurring until after code executes, but I haven't found anything with using a timer. Here is a section of the method that calls the timer if the answer is correct:
BOOL rightChoice = true;
int colorNum;
NSDate *startTime;
NSTimeInterval elapsed;
colorNum = [self randomizeNum:middle];
[self setTextLabel:colorNum];
while (rightChoice){
elapsed = 0.0;
startTime = [NSDate date];
while (elapsed < 2.0){
elapsed = [startTime timeIntervalSinceNow] * -1.0;
NSLog(#"elapsed time%f", elapsed);
}
rightChoice = [self correctChoice:middleStatus :colorNum];
colorNum = [self randomizeNum:middle];
}
One of two things stood out
You're using a while loop as a timer, don't do this - the operation is synchronous.
If this is run on the main thread, and you code doesn't return, your UI will update. The mantra goes: 'when you're not returning you're blocking.'
Cocoa has NSTimer which runs asynchronously - it is ideal here.
So let's get to grips with NSTimer (alternatively you can use GCD and save a queue to an ivar, but NSTimer seems the right way to go).
Make an ivar called timer_:
// Top of the .m file or in the .h
#interface ViewController () {
NSTimer *timer_;
}
#end
Make some start and stop functions. How you call these is up to you.
- (void)startTimer {
// If there's an existing timer, let's cancel it
if (timer_)
[timer_ invalidate];
// Start the timer
timer_ = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:#selector(onTimerFinish:)
userInfo:nil
repeats:NO];
}
- (void)onTimerFinish:(id)sender {
NSLog(#"Timer finished!");
// Clean up the timer
[timer_ invalidate];
timer_ = nil;
}
- (void)stopTimer {
if (!timer_)
return;
// Clean up the timer
[timer_ invalidate];
timer_ = nil;
}
And now
Put your timer test code in the onTimerFinish function.
Make an ivar that stores the current choice. Update this ivar when a choice is made and make the relevant changes to the UI. Call stopTimer if the stop condition is met.
In the onTimerFinished you can conditionally call and startTimer again if you desire.
Hope this helps!

NSTimer invalidate not working

I am trying to create an explosion on the iphone screen which gets bigger fast, then goes away. Why is this timer not stopping?
NSTimer *explosion = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(explosion) userInfo:nil repeats:YES];
-(void)explosion {
image.image = [UIImage imageNamed:#"explosion.png"];
expsize = expsize + 2.5;
image.frame = CGRectMake(image.frame.origin.x, image.frame.origin.y, expsize, expsize);
if (expsize > 60) {
NSLog(#"%f",expsize);
[explosion invalidate];
explosion = nil;
}
}
You are most likely invalidating the wrong timer.
You create a local variable named explosion that has the same name as the instance variable.
Avoid declaring instance variables and local variables with the same name!
I'd suggest that you use the form of selector that the NSTimer doc calls for: - (void)timerFireMethod:(NSTimer*)theTimer. The you can invalidate "theTimer" and be sure you're invalidating the right one.
Also, of course, if "explosion" is declared as a property, then there will be two methods in the class named "explosion", and no real clue as to which one is getting called.
It's hard to be certain, because it's not clear whether this is exactly your code, but you have two variables named explosion, and one of them has an NSTimer assigned to it; the other (which seems to be an ivar) is nil.
// Variable local to whatever method this is in
NSTimer *explosion = [NSTimer scheduledTimerWithTimeInterval:0.1...
if (expsize > 60) {
NSLog(#"%f",expsize);
// Other variable named "explosion" does not exist.
// This is an ivar? Has not been set.
[explosion invalidate];
Assuming you've got explosion declared as a property (and there is no reason not to), you should fix this by using the setter when you create the timer:
[self setExplosion:[NSTimer scheduledTimerWithTimeInterval:...]];
Now the ivar has the timer instance and you can use it to invalidate the timer.
Also, note that your timer's method is incorrect; it must take one parameter which is a pointer to the timer. You can also use this pointer to invalidate the timer when it fires.
- (void) fireExplosion: (NSTimer *)tim {
//...
if( expsize > 60 ){
[tim invalidate];
//...
}
}
Finally, you have one last naming problem; if your property is called explosion, the convention in Cocoa is that the accessor should have the same name, but you have used explosion for the method that your timer calls. This could cause hard-to-track problems later. You should rename the timer method as I have here, using a verb indicating that something is happening.
If you are declaring explosion how you posted in your example then you are shadowing your instance variable explosion. As a word of advice you should use a naming convention for instance variables such as an underscore prefix. Now keeping track of the timer is not required if you only invalidate it after it fires. You could just take an extra parameter on the explosion method that would be the timer explosion:(id)timer. Otherwise you can do the following.
#interface X : NSObject
{
NSTimer *_explosion;
}
#end
And when you go to declare it in your code do the following
...
[_explosion invalidate];
[_explosion release];
//There is a whole 'nother debate on whether or not to retain a scheduled timer
//but I am a stickler for ownership so remember to release this in dealloc
_explosion = [[NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:#selector(explosion)
userInfo:nil
repeats:YES] retain];
...
-(void)explosion {
image.image = [UIImage imageNamed:#"explosion.png"];
expsize = expsize + 2.5;
image.frame = CGRectMake(image.frame.origin.x, image.frame.origin.y, expsize, expsize);
if (expsize > 60) {
NSLog(#"%f",expsize);
[_explosion invalidate];
[_explosion release];
_explosion = nil;
}
}

iPhone NSTimer change repeat time

I have a static method in which I setup NSTimer, but sometimes I need to change repeat time. How to do that if I work with static method? Should be something like this:
+ (void)setupTimer:(BOOL)updateTime newTime:(int)time {
NSTimer *timer;
if (updateTime) {
[timer invalidate];
timer = nil;
}
timer = [NSTimer scheduledTimerWithTimeInterval:time
target:self
selector:#selector(myMethod:)
userInfo:nil
repeats:YES];
}
But it's not working...and I know that I cannot invalidate in this case my timer...but also I cannot use NSTimer declared as member of class in static method...How to be ? thanks....
Just prefix the variable with static.
static NSTimer *timer;
If you overwrite the timer variable, you should invalidate it first, because otherwise you'll have a timer running, that you don't have access to anymore.
I think you should be able to write this without static functions but you can also do this using static functions. If there should be only one instance of that class then use a singleton-pattern.
for doing this with static functions then just use
static NSTimer *timer
but you also have to retain your new and also release the old timer because the function scheduledTimer... allocs an NSTimerinstance but also autoreleases it. If dont retain that timer then the timer will be deallocated later and will afaik not call your method.

NSTimer not stopping

I have a Class with a NSTimer *myTimer; variable. At some point I do:
myTimer = [NSTimer scheduledTimerWithTimeInterval:20 target:self selector:#selector(doStuff) userInfo:nil repeats: YES];
further, I have a method:
- (void)doStuff
{
if(myTimer)
{
//do stuff
}
}
and I stop my timer when the class is released through:
- (void)dealloc
{
if (myTimer) { //if myTimer==nil it already has been stopped in the same way
[myTimer invalidate];
myTimer = nil;
}
}
Now, the problem is that when I release the class the timer goes on and on and on firing the event anyway. Am I doing something wrong? It seems the dealloc method is never called, otherwise myTimer would be nil and even if the selector is fired it would not go into the if(myTimer)
This will never work, because timers retain their target, which means your dealloc method will never get invoked until after you've invalidated the timer.
For more info, see the NSTimer documentation and this blog post on "Dangerous Cocoa Calls"
Have you tried the handy debugger tools at your disposal? What happens if you set a breakpoint in your dealloc method? Also, you should post more context around your creation. Is it possible you're creating the timer more than once, thereby replacing the original (but not invalidating it) and leaving it out there to fire at will?

The error of NSTimer

I add a NSTimer in the iphone application。When I run the application,it‘s failed。I have tracked it and found that it stop at “0x3050c3ad <+0013> call 0x306aeaa5 ” and cann't go on in Debugger。
If you know,please tell me what’s wrong with the application and how to solve it。
Thank you!
The code is:
NSTimer *m_heartBeatTimer;
#property(nonatomic, retain) NSTimer *m_heartBeatTimer;
#synthesize m_heartBeatTimer;
-(void)HeartBeatTimer:(NSTimer *)timer
{
[csocket CloseSocket];
}
case PING:
{
[self SendDataToServer:"00" Type:PONG];
if(m_heartBeatTimer != nil)
[m_heartBeatTimer invalidate];
m_heartBeatTimer = [NSTimer scheduledTimerWithTimeInterval:6.0 target:self selector:#selector(HeartBeatTimer:) userInfo:nil
repeats:NO];
} break;
lqf,
First you should access the timer via self.m_heartBeatTimer since you declared it as retained in the #property declaration. If you don't use the self. prefix, you aren't using the setter and therefore you aren't retaining the timer like you specified in the #property declaration.
I have no clue what your obscure error message is, but I'm guessing it's memory related. Make sure you use that self. prefix and let me know if that works. If you actually had an error message of EXC_BAD_ACCESS output on the Run Console, please update your post with that so it's something people can work with.
-Rob