Ingat juga bahwa siklus penahan dapat terjadi jika blok Anda merujuk ke objek lain yang kemudian dipertahankanself
.
Saya tidak yakin bahwa Pengumpulan Sampah dapat membantu dalam mempertahankan siklus ini. Jika objek mempertahankan blok (yang saya sebut objek server) hidup lebih lama self
(objek klien), referensi keself
dalam blok tidak akan dianggap siklik sampai objek penahan itu sendiri dilepaskan. Jika objek server jauh lebih lama dari kliennya, Anda mungkin memiliki kebocoran memori yang signifikan.
Karena tidak ada solusi bersih, saya akan merekomendasikan solusi berikut. Jangan ragu untuk memilih satu atau lebih dari mereka untuk memperbaiki masalah Anda.
- Gunakan hanya blok untuk penyelesaian , dan bukan untuk acara terbuka. Misalnya, gunakan blok untuk metode suka
doSomethingAndWhenDoneExecuteThisBlock:
, dan bukan metode sukasetNotificationHandlerBlock:
. Blok yang digunakan untuk penyelesaian memiliki akhir yang pasti, dan harus dirilis oleh objek server setelah dievaluasi. Ini mencegah siklus mempertahankan hidup terlalu lama bahkan jika itu terjadi.
- Lakukan tarian referensi lemah yang Anda gambarkan.
- Berikan metode untuk membersihkan objek Anda sebelum dirilis, yang "memutus" objek dari objek server yang mungkin menyimpan referensi untuk itu; dan panggil metode ini sebelum memanggil rilis pada objek. Meskipun metode ini baik-baik saja jika objek Anda hanya memiliki satu klien (atau tunggal dalam beberapa konteks), tetapi akan rusak jika memiliki beberapa klien. Anda pada dasarnya mengalahkan mekanisme penghitungan retain di sini; ini mirip dengan menelepon,
dealloc
bukan release
.
Jika Anda menulis objek server, ambil argumen blokir hanya untuk penyelesaian. Jangan terima argumen blokir untuk panggilan balik, seperti setEventHandlerBlock:
. Alih-alih, kembalilah ke pola delegasi klasik: buat protokol formal, dan iklankan setEventDelegate:
metode. Jangan mempertahankan delegasi. Jika Anda bahkan tidak ingin membuat protokol formal, terima pemilih sebagai panggilan balik delegasi.
Dan terakhir, pola ini seharusnya membunyikan alarm:
- (void) dealloc {
[myServerObject releaseCallbackBlocksForObject: self];
...
}
Jika Anda mencoba melepaskan kaitan blok yang mungkin merujuk self
dari dalam dealloc
, Anda sudah dalam masalah. dealloc
mungkin tidak pernah dipanggil karena mempertahankan siklus yang disebabkan oleh referensi di blok, yang berarti bahwa objek Anda hanya akan bocor sampai objek server dideallocated.
self
proksi sayathis
hanya untuk membalikkan keadaan. Dalam JavaScript saya sebutthis
penutupan sayaself
, jadi rasanya enak dan seimbang. :)