Question

I have the following pair of functions in a MessagePlayerViewController(UIViewController) which move a slider to reflect playback progress of an AVAudioPlayer:

-(void)startTrackingPlayback
{
    if(!self.isPlaying)
    {
        self.isPlaying = YES;
        self.playbackTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateProgress) userInfo:nil repeats:YES];
    }
}

-(void)stopTrackingPlayback
{
    if(self.playbackTimer)
    {
        if(self.playbackTimer.isValid)
        {
            [self.playbackTimer invalidate];
            self.playbackTimer = nil;
        }
    }
    self.isPlaying = NO;
}

Intermittently, and following no discernible pattern, I get an Exec Bad Access ith the top two items in the stack as:

0 objc_msgSend
1 [MessagePlayerViewController stopTrackingPlayback];

How can this be? I check if the timer exists before I call isValid and I check isValid before I invalidate it.

Using a breakpoint I can see that the timer does exist, but the error occurs when I set it to nil. If I remove this line, I get an identical error on the line:

[self.playbackTimer invalidate];
Was it helpful?

Solution

I would suggest inspecting the way you use your MessagePlayerViewController. It seems to me that both the stack trace and the behaviour you describe hint at the fact that it is the controller that is being deallocated earlier than your timer.

Take into account the fact that the run loop where the timer is scheduled will keep the timer alive.

Maybe the fix is as simple as calling invalidate in your controller's dealloc method (or somewhere else where it makes sense), but if you do not provide more code, it is not possible to say.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top