简体   繁体   中英

How to stop an NSTimer that I don't know is released or not

Sorry to ask this question, but it's now day 3 I try to solve this problem and have no progress so far.

The problem is this: during a game there is a pause between the user answered a question and the next question. Also in several other cases there are such pauses in gameplay. For this I use one NSTimer.

In .h I have:

@property(nonatomic,retain) NSTimer *scheduleTimer;

and in the .m

@synthesize scheduleTimer;

scheduleTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target: self selector: @selector(playFeedbackSound) userInfo: nil repeats: NO];

now this works just fine. But when the user exits the ViewController I need to invalidate the timer. Otherwise the timer will fire and then crash the app or pops up stuff that does not belong in the other view etc.

Therefore I write:

- (void)viewWillDisappear:(BOOL)animated {
    [scheduleTimer invalidate];   
}

now this does the job if the timer is actually set. But if there is no such timer scheduled, the app just crashes.

I tried probably everything there is, including @try (which crashes the app too, Zombie says " * -[CFRunLoopTimer invalidate]: message sent to deallocated instance 0x567640"). Since the timer gets released after it is done, a [scheduleTimer isValid] will just crash the app as well.

Now I'm already pretty desperate, and as a last resort I'm thinking of replacing the timer with UIView animateWithDuration that does nothing visible.

However, I think this should be a pretty standard situation. I just don't know why I can't find an answer to this very obvious task. Can you help? Thank you

I think the problem is that the NSTimer gets autoreleased before you invalidate it.

So you should do:

scheduleTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0 target: self selector: @selector(playFeedbackSound) userInfo: nil repeats: NO] retain];

And you should also release the timer in viewWillDisappear:

[scheduleTimer release];

But an even better solution is probably to use the dot property syntax to care of retain/release:

self.scheduleTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target: self selector: @selector(playFeedbackSound) userInfo: nil repeats: NO];

And then:

- (void)viewWillDisappear:(BOOL)animated {
    if (self.scheduleTimer != nil) {
        [self.scheduleTimer invalidate];
        self.scheduleTimer = nil;
    }
}

Create a method to invalidate the timer that also sets the property to nil:

- (void) invalidateTimer
{
    if (self.scheduleTimer) {
       [self.scheduleTimer invalidate];   
       self.scheduleTimer = nil;  
    }
}

... and then call that method whenever you invalidate the timer. For example:

- (void)viewWillDisappear:(BOOL)animated 
{
   [super viewWillDisappear: animated];
   [self invalidateTimer];
}

Make sure your timer is retained by using:

self.scheduleTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target: self selector: @selector(playFeedbackSound) userInfo: nil repeats: NO];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM