iOS - NSTimer - SIGABRT после аннулирования - Изменить сейчас DeAlloc Msg - PullRequest
0 голосов
/ 27 октября 2011

Мой NSTimer встроен в класс, который воспроизводит последовательности изображений. В основном это зацикливает и изменяет UIImageView. Все идет хорошо, если я позволю последовательности изображений закончить, но ... сам по себе, если я пытаюсь остановить таймер во время его воспроизведения, я получаю sigabrt. Edit: больше не sigabrt, но теперь DeAlloc я не могу объяснить.

«Стоп» в конце последовательности кадров - это та же самая остановка, которую я называю средней последовательностью.

Так что может заставить NSTimer нарушать среднюю функцию и 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: Поэтому я закомментировал NSAssert в DeAlloc, комментируя, что пролил немного больше света. Теперь добираемся до self.animationTimer = nil; и говорим *** -ImageAnimator setAnimationTimer:]: Message sent to deallocated instance.

DeAlloc вызывается правильно, когда я делаю таймер недействительным ... поэтому я немного запутался здесь.

Ответы [ 2 ]

0 голосов
/ 21 июня 2013

Хорошо, я написал этот код, чтобы я мог заверить вас, что он должен работать очень хорошо :) Вам нужно вызвать 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];

Прежде чем вы удалите представление из его суперпредставления, и все будет простохорошо.

0 голосов
/ 01 ноября 2011

У меня есть решение, которое работает, но не оптимально.

Я просто добавил другую функцию, чтобы установить кадр, в котором он находится, до последнего кадра, и он завершает последовательность, как мне нужно.

Но это не решает вопрос, почему происходит сбой, если я пытаюсь остановить последовательность в середине выполнения.

...