iOS - NSTimer - SIGABRT sonra geçersiz kılma - Şimdi Düzenle DeAlloc Msg

NSTimer'im görüntü dizileri oynayan bir sınıfa gömülü var. Temel olarak bir UIImageView öğesini çevirir ve değiştirir. Görüntü dizisinin tamamlanmasına izin verirseniz her şey yolunda gider ama eğer oynatılırken zamanlayıcıyı durdurmaya çalışırsam kendiliğinden bir sigabrt elde ederim. Düzenleme: Artık bir sigabrt yok ama şimdi bir DeAlloc açıklayamıyorum.

Bir çerçeve sırasının sonundaki "durdurma", orta diziyi çağıran aynı duraktır.

Yani NSTimer'in orta işlevi ve DeAlloc'ı kırmasına neden olabilir. Daha fazla noktaya, onu düzeltmek için nelere bakabilirim?

Teşekkürler.

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.

// Animasyonu başlatmak için bu yöntemi çağırın.

- (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.

Zamanlayıcıyı geçersiz kıldığımda DeAlloc doğru çağrılıyor ... bu yüzden biraz kafam karıştı.

0
Bunu - (void) animationTimerCallback: (NSTimer *) zamanlayıcı 'yı çağırdıktan sonra ...
katma yazar Gabriel, kaynak
Hmmm DeAlloc'ta bir NSAssert vardı ... ... biraz daha fazla ışık saçtığını söyleyen ... ... şimdi 'self.animationTimer = nil' oluyor. *** -ImageAnimator setAnimationTimer:]: Mesaj ayrılmamış örneğe gönderildi. Zamanlayıcıyı geçersiz kıldıktan sonra DeAlloc çağrılıyor ... bu yüzden biraz kafam karıştı.
katma yazar Mytheral, kaynak
Anladım, bunu nasıl devam ettireceğimi anlamıyorum. Ben stopAnimation komutunu çağırır ve bu işleve girer ve yaptığı ilk şey dehşetli olur ve sonra DeAlloc'a atlar, benim stopAnimation'u çağırdığımda benim app animTimerCallback'i çağırır mı?
katma yazar Mytheral, kaynak
Eğer SIGABRT alıyorsanız, bu genellikle bir iddiaya çarptığınız anlamına gelir. İddianın ne olduğunu görmek için kayıtlarına bak.
katma yazar Rob Napier, kaynak
Erişim yoluyla her zaman erişebilmeniz gerekirken, dealloc büyük bir istisnadır. Ivarınızı doğrudan dealloc içinde bırakın. Bununla birlikte, bu hata, (süper dealloc) dizeğinizin başlangıcında (sonunda çağrılmalıdır) veya self 'in fazla yayınlandığını ileri sürmektedir.
katma yazar Rob Napier, kaynak

2 cevap

Çalıştığım ama optimal olmayan bir çözüm var.

Son kareye ayarlamak için başka bir fonksiyon ekledim ve diziyi ihtiyacım olan gibi bitirir.

Ama bu diziyi çalıştırmayı denediğimde neden çökme sorunu olduğunu çözmüyor.

0
katma

Eh, bu kod yazdım bu yüzden ben sadece iyi çalışıyor olması gerektiğini garanti ederim :) Sen görüş ile bitmeden önce stopAnimating çağırmak gerekir, dealloc içinde assert var tek yolu görünüm ayrılmışsa hala hareketliydi. Bu olmamalı, tam olarak neden orada bir iddia var. Ayrıca, iddiayı açıklayan büyük bir yorum var, bunun hakkında net olmayan nedir?

- (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];
}

Sadece ara:

[view stopAnimating];

Görünümü süper görüntüden kaldırmadan önce her şey iyi olacak.

0
katma