Search code examples
iphoneios4nstimersigabrt

iOS - NSTimer - SIGABRT after invalidate - Edit Now DeAlloc Msg


I have my NSTimer embedded in a class that plays image sequences. Basically it loops and changes a UIImageView. Everything goes well if I let the image sequence finish but... on it's own if I try to stop the timer while it is playing I get a sigabrt. Edit: No longer a sigabrt but now a DeAlloc I can't explain.

The "stop" at the end of a frame sequence is the same stop I am calling mid sequence.

So what might cause an NSTimer to break mid function and DeAlloc. More to the point what might I look at to fix it.

Thanks.

I am using some example code from here: http://www.modejong.com/iOS/PNGAnimatorDemo.zip

Edit: I'll add what I believe to be the pertinent code here.

// Invoke this method to start the animation

- (void) startAnimating
{
    self.animationTimer = [NSTimer timerWithTimeInterval: animationFrameDuration                                         target: self                                      selector: @selector(animationTimerCallback:)                                    userInfo: NULL                                       repeats: TRUE];

    [[NSRunLoop currentRunLoop] addTimer: animationTimer forMode: NSDefaultRunLoopMode];

    animationStep = 0;

    if (avAudioPlayer != nil)
        [avAudioPlayer play];

    // Send notification to object(s) that regestered interest in a start action

    [[NSNotificationCenter defaultCenter]
     postNotificationName:ImageAnimatorDidStartNotification
     object:self];  
}

- (void) animationTimerCallback: (NSTimer *)timer {
    if (![self isAnimating])
        return;

    NSTimeInterval currentTime;
    NSUInteger frameNow;

    if (avAudioPlayer == nil) {
        self.animationStep += 1;

//      currentTime = animationStep * animationFrameDuration;
        frameNow = animationStep;
    } else {
        currentTime = avAudioPlayer.currentTime;
        frameNow = (NSInteger) (currentTime / animationFrameDuration);
    }

    // Limit the range of frameNow to [0, SIZE-1]
    if (frameNow < 0) {
        frameNow = 0;
    } else if (frameNow >= animationNumFrames) {
        frameNow = animationNumFrames - 1;
    }

    [self animationShowFrame: frameNow];
//  animationStep = frameNow + 1;

    if (animationStep >= animationNumFrames) {
        [self stopAnimating];

        // Continue to loop animation until loop counter reaches 0

        if (animationRepeatCount > 0) {
            self.animationRepeatCount = animationRepeatCount - 1;
            [self startAnimating];
        }
    }
}

- (void) stopAnimating
{
    if (![self isAnimating])
        return;

    [animationTimer invalidate];
    self.animationTimer = nil;

    animationStep = animationNumFrames - 1;
    [self animationShowFrame: animationStep];

    if (avAudioPlayer != nil) {
        [avAudioPlayer stop];
        avAudioPlayer.currentTime = 0.0;
        self->lastReportedTime = 0.0;
    }

    // Send notification to object(s) that regestered interest in a stop action

    [[NSNotificationCenter defaultCenter]
     postNotificationName:ImageAnimatorDidStopNotification
     object:self];  
}

Edit2: So I commented out an NSAssert in DeAlloc, commenting that out shed a bit more light. Now getting to self.animationTimer = nil; and saying *** -ImageAnimator setAnimationTimer:]: Message sent to deallocated instance.

DeAlloc is being called right when I invalidate the timer... so I'm a bit confused here.


Solution

  • I have a solution which is working but not optimal.

    I just added another function to set the frame it's on to the last frame and it ends the sequence as I need.

    But it doesn't solve the question of why it's doing it's crashing if I try to stop the sequence mid run.