iOS - NSTimer - 失效后的SIGABRT - 立即编辑DeAlloc消息

时间:2011-10-27 19:47:14

标签: iphone ios4 nstimer sigabrt

我将NSTimer嵌入到播放图像序列的类中。基本上它循环并更改UIImageView。一切顺利,如果我让图像序列完成但是...如果我试着在播放时停止计时器就可以了...我得到了一个sigabrt。编辑:不再是sigabrt,而是现在我无法解释的DeAlloc。

帧序列结束时的“停止”与我调用中间序列的停止相同。

那么可能导致NSTimer打破mid函数和DeAlloc的原因。更重要的是我可以通过什么来解决它。

感谢。

我在这里使用了一些示例代码:http://www.modejong.com/iOS/PNGAnimatorDemo.zip

编辑:我会在此处添加我认为相关的代码。

//调用此方法启动动画

- (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:所以我在DeAlloc中评论了一个NSAssert,评论说明了更多的亮点。现在转到self.animationTimer = nil;并说*** -ImageAnimator setAnimationTimer:]: Message sent to deallocated instance.

当我使计时器无效时,DeAlloc正在被调用...所以我在这里有点困惑。

2 个答案:

答案 0 :(得分:0)

我有一个有效但不是最佳的解决方案。

我刚刚添加了另一个函数来设置它在最后一帧上的帧,它会根据需要结束序列。

但如果我试图在中途停止序列,它并没有解决为什么它会崩溃的问题。

答案 1 :(得分:0)

好吧,我写了这段代码,所以我可以向你保证它应该工作得很好:)你需要在完成视图之前调用stopAnimating,你在dealloc中获得断言的唯一方法是视图在仍然动画时被取消分配。这不应该发生,这正是为什么那里有断言的原因。还有一个很大的评论解释了这个断言,有什么不清楚的?

- (void)dealloc {
  // This object can't be deallocated while animating, this could
  // only happen if user code incorrectly dropped the last ref.

  NSAssert([self isAnimating] == FALSE, @"dealloc while still animating");

  self.animationURLs = nil;
  self.imageView = nil;
  self.animationData = nil;
  self.animationTimer = nil;

  [super dealloc];
}

请致电:

[view stopAnimating];

在从超级视图中删除视图之前,一切都会正常。