dealloc di Swift


145

Saya ingin melakukan pembersihan di akhir kehidupan pengontrol tampilan, yaitu menghapus NSNotificationCenterpemberitahuan. Menerapkan deallochasil dalam kesalahan kompilasi Swift:

Cannot override 'dealloc' which has been marked unavailable

Apa cara yang disukai untuk melakukan pembersihan di akhir kehidupan objek di Swift?

Jawaban:


333
deinit {
    // perform the deinitialization
}

Dari Dokumentasi Swift :

Deinitializer dipanggil segera sebelum instance kelas dideallocated. Anda menulis deinitializers dengan kata kunci deinit, mirip dengan bagaimana penginstalasi dengan kata kunci init. Deinitializers hanya tersedia pada tipe kelas.

Biasanya Anda tidak perlu melakukan pembersihan manual ketika instans Anda tidak dialokasikan. Namun, ketika Anda bekerja dengan sumber daya Anda sendiri, Anda mungkin perlu melakukan pembersihan tambahan sendiri. Misalnya, jika Anda membuat kelas khusus untuk membuka file dan menulis beberapa data untuk itu, Anda mungkin perlu menutup file sebelum instance kelas deallocated.


45
deinit {
    // perform the deinitialization
}

adalah jawaban yang benar untuk Swift "dealloc".

Namun, ada baiknya menunjukkan baru di iOS 9 bahwa NSNotificationCenter tidak perlu lagi dibersihkan!

https://developer.apple.com/library/content/releasenotes/Foundation/RN-FoundationOlderNotes/index.html#X10_11Notes

NSNotificationCenter

Di OS X 10.11 dan iOS 9.0 NSNotificationCenter dan NSDistributedNotificationCenter tidak akan lagi mengirim pemberitahuan ke pengamat terdaftar yang mungkin tidak dialokasikan. Jika pengamat dapat disimpan sebagai referensi zeroing-lemah, penyimpanan yang mendasarinya akan menyimpan pengamat sebagai referensi lemah zeroing, atau jika objek tidak dapat disimpan dengan lemah (yaitu memiliki mekanisme penahan / pelepasan khusus yang akan mencegah runtime dari dapat menyimpan objek dengan lemah) itu akan menyimpan objek sebagai referensi zeroing yang tidak lemah. Ini berarti bahwa pengamat tidak diharuskan untuk tidak mendaftar dalam metode deallokasi mereka. Pemberitahuan berikutnya yang akan dialihkan ke pengamat itu akan mendeteksi referensi nol dan secara otomatis membatalkan pendaftaran pengamat. Jika suatu objek dapat menjadi rujukan yang lemah, notifikasi tidak akan lagi dikirimkan kepada pengamat selama deallokasi; perilaku sebelumnya menerima notifikasi selama dealloc masih ada dalam kasus pengamat referensi yang tidak lemah. Pengamat berbasis blok melalui - [NSNotificationCenter addObserverForName: object: queue: usingBlock] metode masih harus tidak terdaftar ketika tidak lagi digunakan karena sistem masih memegang referensi yang kuat untuk pengamat ini. Menghapus pengamat (baik yang direferensikan dengan lemah atau yang direferensikan) secara prematur masih didukung. CFNotificationCenterAddObserver tidak sesuai dengan perilaku ini karena pengamat mungkin bukan objek. Pengamat berbasis blok melalui - [NSNotificationCenter addObserverForName: object: queue: usingBlock] metode masih harus tidak terdaftar ketika tidak lagi digunakan karena sistem masih memegang referensi yang kuat untuk pengamat ini. Menghapus pengamat (baik yang direferensikan dengan lemah atau yang direferensikan) secara prematur masih didukung. CFNotificationCenterAddObserver tidak sesuai dengan perilaku ini karena pengamat mungkin bukan objek. Pengamat berbasis blok melalui - [NSNotificationCenter addObserverForName: object: queue: usingBlock] metode masih harus tidak terdaftar ketika tidak lagi digunakan karena sistem masih memegang referensi yang kuat untuk pengamat ini. Menghapus pengamat (baik yang direferensikan dengan lemah atau yang direferensikan) secara prematur masih didukung. CFNotificationCenterAddObserver tidak sesuai dengan perilaku ini karena pengamat mungkin bukan objek.

tapi perhatikan poin di bawah ini tentang referensi yang kuat, jadi Anda mungkin harus khawatir tentang pembersihan ...?


3
Kecuali jika blok notifikasi memiliki referensi yang kuat, maka Anda harus menghapus pengamat.
TigerCoding

+1 karena tidak harus membersihkan pengamat. Penting untuk diketahui! Saya membuat semua referensi menangkap lemah sehingga tidak perlu berurusan dengan ini.
n13

2
Blok pemberitahuan sepertinya selalu sangat dirujuk menurut dokumentasi. Jadi: Jika Anda menggunakan blok untuk menangani notifikasi, Anda harus membatalkan registrasi di dalam deinit.
Marsars

22

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Deinitialization.html

Swift secara otomatis mendelokasi instance Anda ketika tidak diperlukan lagi, untuk membebaskan sumber daya. Swift menangani manajemen memori instance melalui penghitungan referensi otomatis (ARC), seperti yang dijelaskan dalam Penghitungan Referensi Otomatis. Biasanya Anda tidak perlu melakukan pembersihan manual ketika instans Anda tidak dialokasikan. Namun, ketika Anda bekerja dengan sumber daya Anda sendiri, Anda mungkin perlu melakukan pembersihan tambahan sendiri. Misalnya, jika Anda membuat kelas khusus untuk membuka file dan menulis beberapa data untuk itu, Anda mungkin perlu menutup file sebelum instance kelas deallocated.

Definisi kelas dapat memiliki paling banyak satu deinitializer per kelas. Deinitializer tidak mengambil parameter apa pun dan ditulis tanpa tanda kurung:

deinit {
    // perform the deinitialization
}

2

menghapus pengamat diperlukan sebelum deallokasi kalau tidak crash akan terjadi. Itu bisa dilakukan menggunakan

deinit {
    // perform the deinitialization
    print("deinit")

    removeObserver(self, forKeyPath: kSelectedViewControllerKey, context: nil)
    removeObserver(self, forKeyPath: kSelectedIndexKey, context: nil)

}

-2

Hati-hati saat memanggil metode di kelas lain dari deinit mungkin akan berakhir dengan crash


1
Diturunkan karena itu tidak harus selalu demikian. Dari ref. docs : Karena sebuah instance tidak dapat dialokasikan kembali sampai setelah deinitializer dipanggil, deinitializer dapat mengakses semua properti dari instance yang dipanggil dan dapat memodifikasi perilakunya berdasarkan pada properti tersebut (seperti mencari nama file yang perlu ditutup).
superjos
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.