Mari kita mulai dengan retain
dan release
; autorelease
benar-benar hanya kasus khusus setelah Anda memahami konsep dasarnya.
Di Cocoa, setiap objek melacak berapa kali itu direferensikan (khususnya, NSObject
kelas dasar mengimplementasikan ini). Dengan memanggil retain
suatu objek, Anda mengatakan kepadanya bahwa Anda ingin menambah jumlah referensinya satu per satu. Dengan memanggil release
, Anda memberi tahu objek yang Anda lepaskan, dan jumlah referensinya berkurang. Jika, setelah memanggil release
, jumlah referensi sekarang nol, maka memori objek tersebut dibebaskan oleh sistem.
Cara dasar ini berbeda dari malloc
danfree
adalah bahwa objek tertentu tidak perlu khawatir tentang bagian lain dari sistem yang mogok karena Anda telah membebaskan memori yang mereka gunakan. Dengan asumsi semua orang bermain bersama dan mempertahankan / melepaskan sesuai dengan aturan, ketika satu bagian kode mempertahankan dan kemudian melepaskan objek, bagian kode lain yang juga mereferensikan objek tidak akan terpengaruh.
Apa yang terkadang membingungkan adalah mengetahui keadaan di mana Anda harus menelepon retain
dan release
. Aturan umum saya adalah bahwa jika saya ingin berpegang pada suatu objek untuk beberapa lama waktu (jika itu adalah variabel anggota di kelas, misalnya), maka saya perlu memastikan jumlah referensi objek tahu tentang saya. Seperti dijelaskan di atas, jumlah referensi objek bertambah dengan pemanggilan retain
. Menurut konvensi, itu juga bertambah (disetel ke 1, sebenarnya) saat objek dibuat dengan metode "init". Dalam salah satu kasus ini, adalah tanggung jawab saya untuk memanggil release
objek tersebut setelah saya selesai. Jika tidak, akan ada kebocoran memori.
Contoh pembuatan objek:
NSString* s = [[NSString alloc] init]; // Ref count is 1
[s retain]; // Ref count is 2 - silly
// to do this after init
[s release]; // Ref count is back to 1
[s release]; // Ref count is 0, object is freed
Sekarang untuk autorelease
. Pelepasan otomatis digunakan sebagai cara yang nyaman (dan terkadang perlu) untuk memberi tahu sistem agar membebaskan objek ini setelah beberapa saat. Dari perspektif perpipaan, saat autorelease
dipanggil, utas saat NSAutoreleasePool
ini diberitahu tentang panggilan tersebut. The NSAutoreleasePool
sekarang tahu bahwa setelah mendapat kesempatan (setelah iterasi saat loop acara), dapat memanggil release
pada objek. Dari sudut pandang kami sebagai programmer, itu mengurus panggilan release
untuk kami, jadi kami tidak perlu (dan sebenarnya, kami tidak seharusnya).
Yang penting untuk diperhatikan adalah bahwa (sekali lagi, menurut konvensi) semua metode kelas pembuatan objek mengembalikan objek yang dirilis secara otomatis. Misalnya, dalam contoh berikut, variabel "s" memiliki jumlah referensi 1, tetapi setelah event loop selesai, variabel itu akan dimusnahkan.
NSString* s = [NSString stringWithString:@"Hello World"];
Jika Anda ingin bergantung pada string itu, Anda harus memanggilnya retain
secara eksplisit, dan kemudian secara eksplisit release
setelah selesai.
Pertimbangkan sedikit kode berikut (sangat dibuat-buat), dan Anda akan melihat situasi di mana autorelease
diperlukan:
- (NSString*)createHelloWorldString
{
NSString* s = [[NSString alloc] initWithString:@"Hello World"];
// Now what? We want to return s, but we've upped its reference count.
// The caller shouldn't be responsible for releasing it, since we're the
// ones that created it. If we call release, however, the reference
// count will hit zero and bad memory will be returned to the caller.
// The answer is to call autorelease before returning the string. By
// explicitly calling autorelease, we pass the responsibility for
// releasing the string on to the thread's NSAutoreleasePool, which will
// happen at some later time. The consequence is that the returned string
// will still be valid for the caller of this function.
return [s autorelease];
}
Saya menyadari semua ini agak membingungkan - pada titik tertentu, itu akan berbunyi klik. Berikut adalah beberapa referensi untuk membantu Anda:
- Pengenalan Apple untuk manajemen memori.
- Cocoa Programming for Mac OS X (4th Edition) , oleh Aaron Hillegas - sebuah buku yang ditulis dengan sangat baik dengan banyak contoh yang bagus. Bunyinya seperti tutorial.
- Jika Anda benar-benar menyelam, Anda bisa menuju ke Peternakan Big Nerd . Ini adalah fasilitas pelatihan yang dijalankan oleh Aaron Hillegas - penulis buku yang disebutkan di atas. Saya menghadiri kursus Pengenalan Kakao di sana beberapa tahun yang lalu, dan itu adalah cara yang bagus untuk belajar.
NSString* s = [[NSString alloc] initWithString:@"Hello World"];
mengembalikan objek autoreleased (saat Anda menulisnya) mengapa saya harus melakukanreturn [s autorelease];
dan menyetelnya "autorelease" lagi dan bukan hanyareturn s
?[[NSString alloc] initWithString:@"Hello World"]
TIDAK akan mengembalikan objek autoreleased. Kapanalloc
pun dipanggil, jumlah referensi disetel ke 1, dan kode tersebut bertanggung jawab untuk memastikannya dirilis. The[NSString stringWithString:]
call, di sisi lain, tidak mengembalikan objek autoreleased.Jika Anda memahami proses penyimpanan / pelepasan maka ada dua aturan emas yang "duh" jelas bagi pemrogram Kakao yang sudah mapan, namun sayangnya hal ini jarang dijabarkan dengan jelas untuk pendatang baru.
Jika fungsi yang mengembalikan objek memiliki
alloc
,create
ataucopy
dalam namanya, maka objek tersebut menjadi milik Anda. Anda harus menelepon[object release]
setelah Anda selesai melakukannya. AtauCFRelease(object)
, jika itu adalah objek Core-Foundation.Jika TIDAK memiliki salah satu dari kata-kata ini dalam namanya, maka objek tersebut milik orang lain. Anda harus memanggil
[object retain]
jika Anda ingin menyimpan objek setelah fungsi Anda berakhir.Anda akan senang juga mengikuti konvensi ini dalam fungsi yang Anda buat sendiri.
(Nitpickers: Ya, sayangnya ada beberapa panggilan API yang merupakan pengecualian dari aturan ini tetapi jarang terjadi).
sumber
Jika Anda menulis kode untuk desktop dan Anda dapat menargetkan Mac OS X 10.5, Anda setidaknya harus menggunakan pengumpulan sampah Objective-C. Ini benar-benar akan menyederhanakan sebagian besar pengembangan Anda - itulah mengapa Apple berupaya semaksimal mungkin untuk membuatnya, dan membuatnya bekerja dengan baik.
Adapun aturan manajemen memori saat tidak menggunakan GC:
+alloc/+allocWithZone:
,+new
,-copy
atau-mutableCopy
atau jika Anda-retain
objek, Anda mengambil kepemilikan itu dan harus memastikan itu dikirim-release
.-release
.-release
Anda dapat mengirimnya sendiri, atau Anda dapat mengirim objek tersebut-autorelease
dan kumpulan rilis otomatis saat ini akan mengirimkannya-release
(sekali per diterima-autorelease
) ketika kumpulan tersebut dikuras.Biasanya
-autorelease
digunakan sebagai cara untuk memastikan bahwa objek hidup selama acara saat ini, tetapi dibersihkan setelahnya, karena ada kumpulan rilis otomatis yang mengelilingi pemrosesan acara Cocoa. Di Cocoa, jauh lebih umum untuk mengembalikan objek ke pemanggil yang dirilis secara otomatis daripada mengembalikan objek yang perlu dilepaskan oleh pemanggil itu sendiri.sumber
Objective-C menggunakan Reference Counting , yang berarti setiap Objek memiliki jumlah referensi. Saat sebuah objek dibuat, ia memiliki jumlah referensi "1". Sederhananya, ketika sebuah objek dirujuk (yaitu, disimpan di suatu tempat), ia "dipertahankan" yang berarti jumlah referensinya bertambah satu. Ketika sebuah objek tidak lagi dibutuhkan, itu "dilepaskan" yang berarti jumlah referensinya berkurang satu.
Saat jumlah referensi objek adalah 0, objek tersebut dibebaskan. Ini adalah penghitungan referensi dasar.
Untuk beberapa bahasa, referensi otomatis bertambah dan berkurang, tetapi tujuan-c bukan salah satu bahasa tersebut. Dengan demikian pemrogram bertanggung jawab untuk menyimpan dan melepaskan.
Cara umum untuk menulis metode adalah:
Masalah keharusan mengingat untuk melepaskan sumber daya yang diperoleh di dalam kode adalah hal yang membosankan dan rawan kesalahan. Objective-C memperkenalkan konsep lain yang bertujuan untuk membuat ini lebih mudah: Kumpulan Autorelease. Kumpulan rilis otomatis adalah objek khusus yang diinstal di setiap utas. Mereka adalah kelas yang cukup sederhana, jika Anda mencari NSAutoreleasePool.
Saat sebuah objek mendapatkan pesan "autorelease" yang dikirim ke sana, objek tersebut akan mencari kumpulan autorelease apa pun yang ada di tumpukan untuk utas saat ini. Ini akan menambahkan objek ke daftar sebagai objek untuk mengirim pesan "rilis" ke beberapa titik di masa mendatang, yang biasanya terjadi ketika kumpulan itu sendiri dilepaskan.
Mengambil kode di atas, kamu bisa menulis ulang menjadi lebih pendek dan mudah dibaca dengan mengatakan:
Karena objek tersebut dirilis otomatis, kita tidak perlu lagi secara eksplisit memanggil "rilis" di atasnya. Ini karena kita tahu beberapa kumpulan rilis otomatis akan melakukannya untuk kita nanti.
Semoga ini membantu. Artikel Wikipedia cukup bagus tentang penghitungan referensi. Informasi lebih lanjut tentang kumpulan rilis otomatis dapat ditemukan di sini . Perhatikan juga bahwa jika Anda membuat untuk Mac OS X 10.5 dan yang lebih baru, Anda dapat memberi tahu Xcode untuk membangun dengan pengumpulan sampah diaktifkan, memungkinkan Anda untuk sepenuhnya mengabaikan pertahankan / rilis / rilis otomatis.
sumber
Joshua (# 6591) - Koleksi Sampah di Mac OS X 10.5 tampaknya cukup keren, tetapi tidak tersedia untuk iPhone (atau jika Anda ingin aplikasi Anda berjalan di Mac OS X versi sebelum 10.5).
Selain itu, jika Anda sedang menulis perpustakaan atau sesuatu yang mungkin digunakan kembali, menggunakan mode GC mengunci siapa pun yang menggunakan kode ke juga menggunakan mode GC, jadi seperti yang saya pahami, siapa pun yang mencoba menulis kode yang dapat digunakan kembali secara luas cenderung pergi untuk mengelola memori secara manual.
sumber
Seperti biasa, ketika orang mulai mencoba menata ulang materi referensi, mereka hampir selalu mendapatkan kesalahan atau memberikan deskripsi yang tidak lengkap.
Apple memberikan penjelasan lengkap tentang sistem manajemen memori Cocoa dalam Panduan Pemrograman Manajemen Memori untuk Cocoa , di bagian akhir terdapat ringkasan singkat namun akurat tentang Aturan Manajemen Memori .
sumber
Saya tidak akan menambahkan spesifik retensi / rilis selain dari yang mungkin Anda pikirkan tentang menjatuhkan $ 50 dan mendapatkan buku Hillegass, tetapi saya sangat menyarankan untuk menggunakan alat Instrumen sejak awal dalam pengembangan aplikasi Anda (bahkan pertama!). Untuk melakukannya, Jalankan-> Mulai dengan alat kinerja. Saya akan mulai dengan Leaks yang hanya salah satu dari banyak instrumen yang tersedia tetapi akan membantu menunjukkan kepada Anda ketika Anda lupa merilisnya. Tidaklah menakutkan berapa banyak informasi yang akan Anda sajikan. Tapi lihat tutorial ini untuk bangun dan bekerja dengan cepat:
TUTORIAL KAKAO: MEMPERBAIKI KEBOCORAN MEMORI DENGAN INSTRUMEN
Sebenarnya mencoba untuk memaksa kebocoran mungkin merupakan cara yang lebih baik, pada gilirannya, belajar bagaimana mencegahnya! Semoga berhasil ;)
sumber
Autorelease tidak menyimpan objek tersebut. Autorelease hanya menempatkannya dalam antrian untuk dirilis nanti. Anda tidak ingin memiliki pernyataan rilis di sana.
sumber
Kumpulan artikel manajemen memori Cocoa saya yang biasa:
manajemen memori kakao
sumber
Ada screencast gratis yang tersedia dari iDeveloperTV Network
Manajemen Memori di Objective-C
sumber
Jawaban NilObject adalah awal yang baik. Berikut beberapa info tambahan yang berkaitan dengan manajemen memori manual ( diperlukan di iPhone ).
Jika Anda sendiri adalah
alloc/init
sebuah benda, ia datang dengan hitungan referensi 1. Anda bertanggung jawab untuk membersihkannya setelah benda itu tidak lagi dibutuhkan, baik dengan menelepon[foo release]
atau[foo autorelease]
. release segera membersihkannya, sedangkan autorelease menambahkan objek ke kumpulan autorelease, yang akan secara otomatis melepaskannya di lain waktu.autorelease terutama untuk saat Anda memiliki metode yang perlu mengembalikan objek yang dipermasalahkan ( jadi Anda tidak bisa melepaskannya secara manual, kalau tidak Anda akan mengembalikan objek nil ) tetapi Anda juga tidak ingin menahannya, .
Jika Anda memperoleh objek di mana Anda tidak memanggil alokasi / init untuk mendapatkannya - misalnya:
tetapi Anda ingin berpegang pada objek ini, Anda perlu memanggil [foo dipertahankan]. Jika tidak, itu mungkin akan didapat
autoreleased
dan Anda akan berpegang pada referensi nihil (seperti padastringWithString
contoh di atas ). Jika Anda tidak lagi membutuhkannya, hubungi[foo release]
.sumber
Jawaban di atas memberikan pernyataan kembali yang jelas tentang apa yang dikatakan dokumentasi; masalah yang dihadapi kebanyakan orang baru adalah kasus-kasus yang tidak berdokumen. Sebagai contoh:
Autorelease : menurut dokumen ini akan memicu rilis "di beberapa titik di masa mendatang". KAPAN?! Pada dasarnya, Anda dapat mengandalkan objek yang ada di sekitar hingga Anda keluar dari kode Anda kembali ke loop peristiwa sistem. Sistem DAPAT melepaskan objek kapan saja setelah siklus kejadian saat ini. (Saya pikir Matt mengatakan itu, sebelumnya.)
String statis :
NSString *foo = @"bar";
- apakah Anda harus menyimpan atau melepaskannya? Tidak. Bagaimana...
Aturan Penciptaan : Jika Anda membuatnya, Anda adalah pemiliknya, dan diharapkan untuk merilisnya.
Secara umum, cara pemrogram Cocoa baru menjadi kacau adalah dengan tidak memahami rutinitas mana yang mengembalikan objek dengan a
retainCount > 0
.Berikut ini potongan dari Very Simple Rules For Memory Management In Cocoa :
Poin pertama mengatakan: jika Anda memanggil
alloc
(ataunew fooCopy
), Anda perlu memanggil rilis pada objek itu.Poin ke-2 mengatakan: jika Anda menggunakan konstruktor kenyamanan dan Anda membutuhkan objek untuk berkeliaran (seperti dengan gambar yang akan digambar nanti), Anda perlu mempertahankan (dan kemudian melepaskannya).
Yang ketiga harus cukup jelas.
sumber
Banyak informasi bagus tentang cocoadev juga:
sumber
Seperti yang telah disebutkan beberapa orang, Pengenalan Manajemen Memori Apple sejauh ini adalah tempat terbaik untuk memulai.
Satu tautan berguna yang belum saya lihat sebutkan adalah Manajemen Memori Praktis . Anda akan menemukannya di tengah-tengah dokumen Apple jika Anda membacanya, tetapi perlu ditautkan secara langsung. Ini adalah ringkasan eksekutif brilian dari aturan manajemen memori dengan contoh dan kesalahan umum (pada dasarnya apa yang coba dijelaskan oleh jawaban lain di sini, tetapi tidak juga).
sumber