Kapan saya harus melepaskan objek di - (void) viewDidUnload daripada di -dealloc?

Jawaban:

51

Selain apa yang telah ditunjukkan, saya ingin menjelaskan lebih lanjut tentang logika di baliknya -viewDidUnload.

Salah satu alasan terpenting untuk mengimplementasikannya adalah bahwa UIViewControllersubclass biasanya juga berisi referensi yang memiliki berbagai subview dalam hierarki tampilan. Properti ini dapat diatur melalui IBOutletssaat memuat dari nib, atau secara terprogram di dalam -loadView, misalnya.

Kepemilikan tambahan subview dengan UIViewControllercara bahwa meskipun pandangannya dihapus dari hierarki tampilan dan dilepaskan untuk menghemat memori, yang melaluinya subview juga dilepaskan oleh tampilan, mereka tidak akan benar-benar dibatalkan alokasinya karena UIViewControlleritu sendiri masih berisi outstanding miliknya sendiri. mempertahankan referensi ke objek tersebut juga. Melepaskan UIViewControllerkepemilikan tambahan dari objek-objek ini memastikan mereka akan dibatalkan alokasinya juga untuk mengosongkan memori.

Objek yang Anda lepaskan di sini biasanya dibuat ulang dan disetel lagi saat UIViewControllertampilannya re-loaded, baik dari Nib atau melalui implementasi -loadView.

Juga perhatikan bahwa UIViewController viewproperti tersebut nilpada saat metode ini dipanggil.

Sean Patrick Murphy
sumber
1
Anda harus membaca developer.apple.com/library/ios/#featuredarticles/… untuk memahami siklus hidup pengontrol tampilan / tampilan
Paul Solt
21

Seperti yang dikatakan dalam dokumentasi :

Ini dipanggil selama kondisi memori rendah ketika pengontrol tampilan perlu melepaskan tampilannya dan objek apa pun yang terkait dengan tampilan tersebut untuk mengosongkan memori.

Dalam situasi yang sama deallocyang tidak disebut. Metode ini hanya tersedia di OS3 ke atas. Berurusan dengan situasi yang sama di iPhone OS 2.x benar-benar menyakitkan!

Pembaruan Juli 2015 : Perlu dicatat bahwa viewDidUnloaditu tidak digunakan lagi di iOS 6 karena "Tampilan tidak lagi dihapus dalam kondisi memori rendah sehingga metode ini tidak pernah dipanggil." Jadi, saran modern jangan khawatir tentang itu dan gunakan dealloc.

Stephen Darlington
sumber
6
Juga dari dokumen: "Anda harus melakukan ini hanya untuk objek yang dapat Anda buat dengan mudah nanti, baik dalam metode viewDidLoad Anda atau dari bagian lain aplikasi Anda. Anda tidak boleh menggunakan metode ini untuk merilis data pengguna atau informasi lain yang tidak dapat mudah dibuat ulang ". Itu pertanyaan yang saya miliki juga, terima kasih!
leolobato
Bagaimana jika tampilan saat ini terlihat? Bukankah buruk untuk menjatuhkannya karena peringatan memori rendah? ;) maka aplikasi akan kosong kosong. Saya tidak mengerti maksud melepaskan tampilan karena memori rendah. Jika saya tidak melihat tampilan, saya selalu melepaskan seluruh pengontrol. Althogh saya memiliki pengontrol tampilan root yang tetap utuh dan mengelola semua pemuatan / pembongkaran pengontrol tampilan anak itu ...
Terima kasih
Tidak, Anda tidak akan menggunakan ini jika Anda hanya menukar satu tampilan dengan yang lain. Pikirkan kasus di mana Anda memiliki "tumpukan" tampilan dengan UINavigationController. Hanya satu tampilan yang terlihat dan, jika Anda memiliki peringatan memori, Anda dapat melepaskan semua yang tidak terlihat.
Stephen Darlington
Bagaimana Anda mengontrol viewDidUnload yang tidak dipanggil pada tampilan yang terlihat saat ini seperti yang telah dicatat Terima kasih?
arielcamus
1
viewDidUnload tidak akan dipanggil pada tampilan yang terlihat saat ini, hanya pada tampilan yang tidak terlihat.
progrmr
9

Ini karena Anda biasanya akan menyetel @propertysebagai "(nonatomic, retain)"dan sebagai penyetel yang dibuat untuk Anda melepaskan objek saat ini dan kemudian mempertahankan argumen yaitu

self.property = nil;

... melakukan sesuatu di sepanjang baris:

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

Oleh karena itu Anda membunuh dua burung dengan satu batu: manajemen memori (melepaskan objek yang ada) dan menetapkan penunjuk ke nil (karena mengirim pesan apa pun ke penunjuk nil akan mengembalikan nihil).

Semoga membantu.

gazzaaa87
sumber
8

Ingat itu viewDidUnloadadalah metode dalam pengontrol tampilan, bukan dalam tampilan. Metode tampilan dealloc akan dipanggil saat tampilan dibongkar, tetapi metode pengontrol tampilan dealloc mungkin tidak dipanggil hingga nanti.

Jika Anda mendapatkan peringatan memori rendah dan tampilan Anda tidak muncul, yang akan terjadi misalnya kapan saja Anda menggunakan UIImagePickerController untuk mengizinkan pengguna mengambil gambar, tampilan Anda akan dibongkar dan harus dimuat ulang setelah itu.

David Maymudes
sumber
itu masuk akal. Apa yang terjadi jika saya selalu melepaskan seluruh pengontrol tampilan? Itulah yang sebenarnya saya lakukan. Dalam hal ini, saya tidak perlu banyak berurusan dengan -viewDidUnload, bukan? Saya tidak pernah mengalami situasi di mana saya hanya akan menjatuhkan tampilan, karena saya selalu menjatuhkan seluruh pengontrol jika tidak terlihat.
Terima kasih
baik, ingatlah bahwa dalam kasus di mana tampilan Anda ditampilkan, tetapi Anda memiliki tampilan layar penuh seperti ImagePicker di atasnya, tampilan Anda mungkin akan diturunkan bahkan jika Anda tidak merencanakannya.
David Maymudes
6

Kesimpulan:

View Controllers memiliki properti view. Biasanya ujung atau potongan kode menambahkan tampilan lain ke tampilan ini. Ini sering terjadi di dalam metode -viewDidLoad, seperti ini:

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

selain itu, file ujung pena dapat membuat tombol dan menambahkannya ke tampilan pengontrol tampilan.

Pada iPhone OS 2.2, ketika -didReceiveMemoryWarning dipanggil dari sistem, Anda harus melepaskan sesuatu untuk mengosongkan memori. Anda bisa melepaskan tampilan seluruh pengontrol tampilan jika itu masuk akal. Atau hanya konten yang menghabiskan banyak memori di dalamnya.

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

Sekarang, di OS 3.0 yang baru, ada metode -viewDidUnload, yang akan dipanggil dari sistem ketika view telah dibongkar karena memori yang rendah (tolong koreksi saya: kapan tepatnya ini dipanggil?)

-viewDidUnload digunakan untuk melepaskan semua objek yang dimiliki oleh pengontrol tampilan itu sendiri dan tampilan. Alasan: Jika pengontrol tampilan menyimpan referensi ke turunan tampilan, yaitu tombol, tampilan turunan yang direferensikan tidak akan dirilis, karena jumlah penahannya adalah> = 1. Setelah dirilis di -viewDidUnload, mereka bisa dibebaskan dari ingatan.

Terima kasih
sumber
1
Ingat dalam pandangan tidak membongkar untuk melakukan self.button = nil ;, bukan [tombol lepas] ;.
mk12
6

Apple menghentikan viewWillUnload, sekarang Anda harus menggunakan didReceiveMemoryWarning atau dealloc untuk merilis objek Anda.

Di iOS 6, metode viewWillUnload dan viewDidUnload UIViewController sekarang tidak digunakan lagi. Jika Anda menggunakan metode ini untuk merilis data, gunakan metode didReceiveMemoryWarning. Anda juga dapat menggunakan metode ini untuk merilis referensi ke tampilan pengontrol tampilan jika tidak sedang digunakan. Anda perlu menguji bahwa tampilan tidak ada di jendela sebelum melakukan ini.

Guilherme Torres Castro
sumber
5

Jika pengontrol tampilan dimunculkan dari tumpukan pengontrol navigasi dan tidak dipertahankan di tempat lain, alokasinya akan dibatalkan, dan dealloc akan dipanggil sebagai ganti viewDidUnload. Anda harus merilis tampilan yang dibuat di loadView dalam dealloc, tetapi tidak perlu menyetel variabel ke nil, karena segera setelah dealloc dipanggil, variabel tidak akan ada lagi.

Colin
sumber
3

Anda bisa merilis subview yang Anda pegang, misalnya UIImageView yang Anda pertahankan dalam metode loadView, atau lebih baik lagi gambar yang ada di UIImageView tersebut.

drvdijk.dll
sumber