Saya tertarik untuk memahami keadaan yang membuat pengembang mengganti + menginisialisasi atau + memuat. Dokumentasi memperjelas metode ini dipanggil untuk Anda oleh runtime Objective-C, tetapi hanya itu yang jelas dari dokumentasi metode tersebut. :-)
Rasa ingin tahu saya datang dari melihat kode contoh Apple - MVCNetworking. Kelas model mereka memiliki +(void) applicationStartup
metode. Ia melakukan beberapa housekeeping pada filesystem, membaca NSDefaults, dll dll ... dan, setelah mencoba menggunakan metode kelas NSObject, sepertinya pekerjaan kebersihan ini mungkin baik-baik saja untuk dimasukkan ke dalam + load.
Saya memang memodifikasi proyek MVCNetworking, menghapus panggilan di App Delegate ke + applicationStartup, dan memasukkan bit housekeeping ke + memuat ... komputer saya tidak terbakar, tetapi itu tidak berarti itu benar! Saya berharap untuk mendapatkan pemahaman tentang seluk-beluk, gotcha, dan apa pun di sekitar metode penyiapan khusus yang harus Anda panggil versus + memuat atau + menginisialisasi.
Untuk + memuat dokumentasi mengatakan:
Pesan muat dikirim ke kelas dan kategori yang dimuat secara dinamis dan ditautkan secara statis, tetapi hanya jika kelas atau kategori yang baru dimuat mengimplementasikan metode yang dapat merespons.
Kalimat ini kludgey dan sulit diurai jika Anda tidak tahu arti sebenarnya dari semua kata. Tolong!
Apa yang dimaksud dengan "yang dimuat secara dinamis dan terhubung secara statis?" Dapatkah sesuatu dimuat secara dinamis DAN ditautkan secara statis, atau apakah keduanya saling eksklusif?
"... kelas atau kategori yang baru dimuat mengimplementasikan metode yang dapat merespons" Metode apa? Menanggapi bagaimana?
Adapun + inisialisasi, dokumentasi mengatakan:
menginisialisasi itu dipanggil hanya sekali per kelas. Jika Anda ingin melakukan inisialisasi independen untuk kelas dan untuk kategori kelas, Anda harus mengimplementasikan metode beban.
Saya mengartikan ini sebagai, "jika Anda mencoba untuk mengatur kelas ... jangan gunakan inisialisasi." Oke, baiklah. Kapan atau mengapa saya mengganti inisialisasi?
sumber
+load
dikirim secara terpisah untuk kategori; artinya, setiap kategori di kelas mungkin berisi+load
metodenya sendiri .initialize
akan dipanggil dengan benar oleh sebuahload
metode, jika perlu, karenaload
referensi pembuatan ke entitas yang tidak diinisialisasi. Ini bisa (anehnya, tapi masuk akal) mengarah padainitialize
lari sebelumnyaload
! Itulah yang saya amati. Ini sepertinya bertentangan dengan "Dan pada saat Anda menerimainitialize
, setiap kelas dalam proses Anda seharusnya sudah menerimaload
(jika sesuai)."load
lebih dulu. Anda kemudian dapat menerimainitialize
saatload
masih berjalan.Artinya adalah jangan menimpa
+initialize
dalam kategori, Anda mungkin akan merusak sesuatu.+load
dipanggil sekali per kelas atau kategori yang diimplementasikan+load
, segera setelah kelas atau kategori tersebut dimuat. Jika tertulis "ditautkan secara statis", artinya dikompilasi ke dalam biner aplikasi Anda. The+load
metode pada kelas dengan demikian disusun akan dieksekusi ketika meluncurkan aplikasi Anda, mungkin sebelum memasukimain()
. Ketika dikatakan "dimuat secara dinamis", itu berarti dimuat melalui paket plugin atau panggilan kedlopen()
. Jika Anda menggunakan iOS, Anda dapat mengabaikan kasus itu.+initialize
dipanggil pertama kali pesan dikirim ke kelas, tepat sebelum menangani pesan itu. Ini (jelas) hanya terjadi sekali. Jika Anda menimpa+initialize
dalam kategori, salah satu dari tiga hal akan terjadi:Inilah sebabnya mengapa Anda tidak boleh menimpa
+initialize
dalam suatu kategori - sebenarnya cukup berbahaya untuk mencoba dan mengganti metode apa pun dalam suatu kategori karena Anda tidak pernah yakin apa yang Anda gantikan atau apakah penggantian Anda sendiri akan diganti oleh kategori lain.BTW, masalah lain yang perlu dipertimbangkan
+initialize
adalah jika seseorang membuat subkelas Anda, Anda berpotensi dipanggil sekali untuk kelas Anda dan sekali untuk setiap subkelas. Jika Anda melakukan sesuatu seperti menyiapkanstatic
variabel, Anda pasti ingin mencegahnya: dengandispatch_once()
atau dengan mengujiself == [MyClass class]
.sumber