Nesneleri -dealloc yerine - (void) viewDidUnload'da ne zaman serbest bırakmalıyım?


Yanıtlar:


51

Daha önce belirtilmiş olana ek olarak, mantık hakkında daha fazla detay vermek istedim -viewDidUnload.

Bunu uygulamanın en önemli nedenlerinden biri, UIViewControlleralt sınıfların genellikle görünüm hiyerarşisindeki çeşitli alt görünümlere ait referansları da içermesidir. Bu özellikler , örneğin IBOutletsbir uçtan yüklenirken veya programlı olarak içeride ayarlanmış olabilir -loadView.

Alt görünümlerin ek mülkiyeti UIViewController, görünümü görünüm hiyerarşisinden kaldırıldığında ve hafızadan tasarruf etmek için serbest bırakıldığında bile, alt görünümlerin de görünüm tarafından serbest bırakıldığı durumlarda, gerçekte ayrılmayacaktır çünkü UIViewControllerkendisi hala kendi olağanüstü halini içermektedir. bu nesnelere referansları korumak. UIViewControllerBu nesnelerin ek sahipliğinin serbest bırakılması, bellek boşaltmak için bunların yanı sıra ayrılmalarını sağlar.

Burada serbest bıraktığınız nesneler genellikle yeniden oluşturulur ve UIViewControllergörünüm re-loadedbir Uçtan ya da -loadView.

Ayrıca, UIViewController viewözelliğin, nilbu yöntemin çağrıldığı zaman olduğunu unutmayın .


1
Görüntüleme / görüntüleme denetleyicisinin yaşam döngüsünü anlamak için developer.apple.com/library/ios/#featuredarticles/… okumalısınız
Paul Solt

21

Gibi belgeler diyor :

Düşük bellek koşullarında, görünüm denetleyicisinin belleği boşaltmak için görünümünü ve bu görünümle ilişkili nesneleri serbest bırakması gerektiğinde çağrılır.

Aynı durumda deallocolan değil denir. Bu yöntem yalnızca OS3 ve üzeri sürümlerde mevcuttur. İPhone OS 2.x'de aynı durumla başa çıkmak gerçek bir acıydı!

Temmuz 2015 Güncellemesi : viewDidUnload"Görünümler artık düşük bellek koşullarında temizlenmediği ve bu nedenle bu yöntem hiçbir zaman çağrılmadığı" için iOS 6'da kullanımdan kaldırıldığını belirtmek gerekir . Yani, modern tavsiye bunun için endişelenip kullanmamaktır dealloc.


6
Ayrıca belgelerden: "Bunu yalnızca, viewDidLoad yönteminizde veya uygulamanızın diğer bölümlerinden daha sonra kolayca yeniden oluşturabileceğiniz nesneler için yapmalısınız. Bu yöntemi, kullanıcı verilerini veya başka herhangi bir bilgiyi serbest bırakmak için kullanmamalısınız kolayca yeniden yaratılabilir ". Bu benim de kendime sorduğum bir soru, teşekkürler!
leolobato

Ya görünüm şu anda görünüyorsa? Düşük hafıza uyarısı yüzünden düşürmek kötü olmaz mıydı? ;) daha sonra uygulama boş bırakılır. Hafızanın yetersiz olması nedeniyle görünümü serbest bırakma noktasını anlamıyorum. Bir manzara görmezsem, her zaman tüm denetleyiciyi serbest bırakırım. Yine de, elimde sağlam kalan ve çocuk görüntüleme denetleyicilerinin tüm yükleme / boşaltma işlemlerini yöneten bir kök görüntüleme denetleyicim var ...
Teşekkürler

Hayır, bir görünümü diğeriyle değiştirirseniz bunu kullanmazsınız. Bir UINavigationController ile bir "yığın" görünümünüzün olduğu durumu düşünün. Yalnızca bir görünüm görünür ve bir hafıza uyarınız varsa, görünmeyenlerin hepsini bırakabilirsiniz.
Stephen Darlington

Thanks'in de belirttiği gibi, viewDidUnload'ın mevcut görünür görünümde çağrılmayacağını nasıl kontrol edersiniz?
arielcamus

1
viewDidUnload, şu anda görünür olan görünümde çağrılmaz, yalnızca görünür olmayan görünümlerde çağrılır.
progrmr

9

Bu genellikle koyacaktır nedeni @propertyolarak "(nonatomic, retain)"ve geçerli nesneyi serbest bırakır için oluşturulan bu tür koyucu olarak ve daha sonra argüman ie korur

self.property = nil;

... şu satırlarda bir şey yapar:

[property release];
property = [nil retain];

Bu nedenle, bir taşla iki kuş vuruyorsunuz: hafıza yönetimi (mevcut nesneyi serbest bırakmak) ve işaretçiyi sıfıra atamak (bir sıfır işaretçisine herhangi bir mesaj göndermek sıfıra döneceğinden).

Umarım yardımcı olur.


8

Bunun viewDidUnloadgörünümde değil, görünüm denetleyicisinde bir yöntem olduğunu unutmayın . Görünümün dealloc yöntem zaman görünümü kaldırılırken denilen olsun, ancak görünüm kontrolörün dealloc yöntem sonrasına kadar denilen edilmeyebilir.

Düşük bellek uyarısı alırsanız ve görünümünüz görünmüyorsa, örneğin kullanıcının bir resim çekmesine izin vermek için bir UIImagePickerController kullandığınızda bu durum meydana gelir, görünümünüz kaldırılır ve bundan sonra yeniden yüklenmesi gerekir.


mantıklı. Her zaman tüm görüntü denetleyicisini düşürürsem ne olur? Aslında yaptığım şey bu. Bu durumda -viewDidUnload ile fazla uğraşmam gerekmiyor, değil mi? Hiçbir zaman sadece manzarayı bırakacağım bir duruma sahip olmadım, çünkü zaten görünmüyorsa her zaman tüm kontrolcüyü bırakıyorum.
teşekkürler

Pekala, görünümünüzün gösterildiği bir durumda, ancak üzerinde ImagePicker gibi bir tam ekran görünümünüz varsa, olmasını planlamamış olsanız bile görünümünüzün kaldırılabileceğini unutmayın.
David Maymudes

6

Sonuç:

Görünüm Denetleyicilerinin bir görünüm özelliği vardır. Genellikle bir uç veya kod parçası bu görünüme başka görünümler ekler. Bu genellikle bir -viewDidLoad yöntemi içinde şu şekilde gerçekleşir:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self createManyViewsAndAddThemToSelfDotView];
}

ek olarak, bir uç dosyası bir düğme oluşturabilir ve bunu görünüm denetleyicisinin görünümüne ekleyebilir.

İPhone OS 2.2'de, sistemden -didReceiveMemoryWarning çalıştırıldığında, belleği boşaltmak için bir şeyler yayınlamanız gerekiyordu. Bu mantıklıysa, tüm görüntü denetleyicisinin görüşünü serbest bırakabilirsiniz. Ya da sadece büyük hafıza tüketen içerikler.

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
    // Release anything that's not essential, such as cached data
}

Şimdi, yeni OS 3.0'da, düşük bellek nedeniyle görünüm kaldırıldığında sistemden çağrılacak bir -viewDidUnload yöntemi var (lütfen beni düzeltin: bu tam olarak ne zaman çağrılıyor?)

-viewDidUnload, hem görünüm denetleyicisinin hem de görünümün sahip olduğu tüm nesneleri serbest bırakmak için kullanılır. Nedeni: Bir görünüm denetleyicisi görünümün alt öğelerine, yani bir düğmeye, başvurulara sahipse, başvurulan alt görünümler serbest bırakılmayacaktır çünkü tutma sayıları> = 1'dir. İn -viewDidUnload yayınlandıktan sonra serbest bırakılabilirler. hafızadan.


1
görünümdeki hatırlatıcı self.button = nil;, [düğme bırakma]; yapmak için kaldırmadı.
mk12

6

Apple kullanımdan kaldırıldı viewWillUnload, şimdi objetc'lerinizi serbest bırakmak için didReceiveMemoryWarning veya dealloc kullanmanız gerekir.

İOS 6'da, UIViewController'ın viewWillUnload ve viewDidUnload yöntemleri artık kullanımdan kaldırılmıştır. Verileri serbest bırakmak için bu yöntemleri kullanıyorsanız, bunun yerine didReceiveMemoryWarning yöntemini kullanın. Bu yöntemi, kullanılmıyorsa, görünüm denetleyicisinin görünümüne başvuruları yayınlamak için de kullanabilirsiniz. Bunu yapmadan önce görünümün bir pencerede olmadığını test etmeniz gerekir.


5

Görünüm denetleyicisi gezinti denetleyicisi yığınından çıkarılırsa ve başka hiçbir yerde tutulmazsa, serbest bırakılır ve viewDidUnload yerine dealloc çağrılır. LoadView'da oluşturulan görünümleri dealloc'ta serbest bırakmalısınız, ancak değişkenleri nil olarak ayarlamak gerekli değildir, çünkü dealloc çağrıldıktan kısa bir süre sonra değişkenler artık mevcut olmayacaktır.


3

Tuttuğunuz tüm alt görünümleri, örneğin, loadView yönteminizde tuttuğunuz UIImageView veya daha iyisi, o UIImageView üzerindeki görüntüyü serbest bırakabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.