2013-10-31 13 views
7

Uygulamamın, uygulamanın kullanımındaki belirli bir noktada bellek basıncı nedeniyle sonlandırılıyor ve sorunun nedenini bir soruna neden olan kodun bir bölümüne indirdim.Bilinen bir nedenden dolayı bellek baskısı nedeniyle sonlandırma, bilinmeyen bir çözüm

Aşağıdaki kod parçasını kopyalayacağım, ancak önce ne yaptığını açıklayacağım.

Açıklama:

Ben videolar içeren bir liste boyunca yineleme olan döngü için. Her video için for döngüsü içeren scrollview boyutunu artırır, bir etiket ve bir düğme (her ikisi de videoya aittir) çeker ve videonun küçük resmini eşzamansız olarak yakalar ve düğmenin altına yerleştirir.

Sorun:

küçük parçasını kapma sorundur. Zaman uyumsuz olarak yapıldığı gerçeğinin, senkronize olarak denediğim ve fesih hala gerçekleştiği için sorun olduğunu düşünmüyorum. Küçük resmi (aşağıdaki kodun tüm zaman uyumsuz kısmı) alan kodu açıkladığımda uygulama çökmez.

Kod:

NB: Ben kısalık için bazı durumlarda kodunu değiştirmek için bir yorum kullanıyorum.

for (int i = [_videoURLs count]-1; i >= 0 ; i--) 
    { 
     //increase the scrollview size 

     //get background image: 
     dispatch_async(screenshotQueue, ^{ 

      AVURLAsset *as = [[AVURLAsset alloc] initWithURL:currentURL options:nil]; 
      AVAssetImageGenerator *ima = [[AVAssetImageGenerator alloc] initWithAsset:as]; 
      ima.appliesPreferredTrackTransform = YES; 
      NSError *err = NULL; 
      CMTime time = CMTimeMake(1, 24); 
      CGImageRef imgRef = [ima copyCGImageAtTime:time actualTime:NULL error:&err]; 
      UIImage *thumbnail = [[UIImage alloc] initWithCGImage:imgRef]; 

      dispatch_async(dispatch_get_main_queue(), ^{ 

       UIImageView *backgroundImage = [[UIImageView alloc]initWithFrame:buttonFrame]; 
       backgroundImage.image = thumbnail; 
       backgroundImage.layer.opacity = 0; 
       [self.videoScrollView addSubview:backgroundImage]; 

       [self.videoScrollView sendSubviewToBack:backgroundImage]; 

       [UIView animateWithDuration:0.5 delay:0.0 options: UIViewAnimationOptionCurveEaseInOut 
       animations:^{ 
        backgroundImage.layer.opacity = 1; 
       } 
       completion:^(BOOL finished){}]; 

      }); 

     }); 

     //add title to the screen caps 

     //draw the button 

    } 

Ben kendini öğretti olduğum iOS 7 ile yeni bir cihazda test, Xcode 5 çıkıyorum, bu yüzden ben kötü alışkanlıkları payını aldı eminim, ama ben biraz daha deneyime sahip birinin alacağı belli bir şeyi kaçırdığımı umuyordum.

Yığın taşmasını doğru bir şekilde araştırıp denedim ve sorunu daha ayrıntılı bir şekilde izole etmek için tanılama, günlükler ve bellek profillerine bakmayı denedim.

Herhangi bir yardım çok takdir edilecektir!

Düzenleme: hatayı yeniden nasıl

:

  1. Git Video listesine
  2. bırak Video listesi
  3. tekrarlayın 1 + 2 4 veya 5 kez çökmesine neden olur

Adım 2. sadece tüm scrollView'ı üstünden kaldırır rview ve daha sonra yeniden çizer. Anladığım kadarıyla her seferinde video listesini yeniden listelemek gerekli değil, ama bunu belli bir nedenden dolayı yapıyorum ve bunun sorunun kaynağı olduğuna inanmıyorum (yanlış olabilirim).

Düzenleme 2:

İşte bellek profilin bir görüntü var: enter image description here

+0

Instruments tahsisleri bölümü üzerinden uygulamayı çalıştırın. Hafızayı/nesneleri bırakmayan şeyleri görmek için hangi nesnelerin veya bellek bloğunun beklenmedik şekilde büyüdüğünü bulup geçmişlerine bakın. – rmaddy

+0

Kaydırma görünümüne çok fazla küçük resim görüntüsü ekliyor olabilirsiniz. Bunların hepsinin hafızada saklandığını unutmayın. Belirli sayıda küçük resim ekledikten sonra sorunu oldukça tutarlı bir şekilde görüyor musunuz? –

+0

@rmaddy Tahsisat aracını çalıştırmayı denedim ve kafa karıştırıcı olan şey, çarpışmayı tetiklediğimde grafiğin artmayacağı. Başka bir yorumda bir ekran görüntüsü ekleyeceğim – MattLoszak

cevap

11

Gösterdiğiniz kodda büyük bir sızıntı var. Sen bir çekirdek Vakfı nesnesi oluştururken:

CGImageRef imgRef = [ima copyCGImageAtTime:time actualTime:NULL error:&err]; 

henüz hiçbir karşılık gelen CFRelease görüyoruz.

Sen kodu olmalıdır:

CGImageRef imgRef = [ima copyCGImageAtTime:time actualTime:NULL error:&err]; 
UIImage *thumbnail = [[UIImage alloc] initWithCGImage:imgRef]; 
CFRelease(imgRef); 
+0

D ' Oh, öyleydi. Çok basit bir şey olacağını umuyordum! Bunun, soruya eklediğim herhangi bir fikir, soruya ekledim mi? – MattLoszak

+1

Aletleri kullanmaya çalıştığımda her zaman gözyaşları içinde gelirim - aslında gerçek gözyaşları, sanal gözyaşları. Aletler, birgün ustalaşmak için kovalar listemde. Birkaç gün önce WWDC oturumunu izledim - 2012 veya 2011'den - ve pencerenin tümünde sunucu üst üste atladığında biraz daha "ağladım" ... –

+3

Aynı zamanda "CGImageRelease (imgRef)" eşdeğerini de kullanabilirsiniz. –

1

Tamam, bu yüzden iyi bir çözüm buldu. Yine de bunun neden ilk etapta bir sorun olduğuna emin değilim, ama bazı şüphelerim var.

Bir küçük resim oluşturma işleminin, bir döngü üzerinde bir iş parçacığında tekrar tekrar yapmak için çok yoğun olduğuna inanıyorum. Bu önsezim vardı ve bu yüzden yukarıdaki kodu düzeltmeye karar verdim. Her defasında yeni bir küçük resim oluşturmak yerine, yeni oluşturulan ekran görüntülerini ev dizini için bir png olarak kaydederdim. Sonra bir dahaki sefere bu kaynağı oradan yüklerdim. Bu hafıza sorunlarının kaybolmasına neden oldu.

Umarım bu, benzer bir sorunu olan birine yardımcı olur - ve eğer birisi eklemek için bir şey varsa veya daha iyi bir cevap varsa, ben tüm kulaklarım.

İlgili konular