Saya memiliki kelas C obyektif. Di dalamnya, saya membuat metode init dan menyiapkan NSNotification di dalamnya
//Set up NSNotification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(getData)
name:@"Answer Submitted"
object:nil];
Di mana saya mengatur [[NSNotificationCenter defaultCenter] removeObserver:self]
di kelas ini? Saya tahu bahwa untuk a UIViewController
, saya bisa menambahkannya ke dalam viewDidUnload
metode Jadi apa yang perlu dilakukan jika saya baru saja membuat Kelas c tujuan?
-(void)dealloc
dan kemudian menambahkannyaremoveObserser:self
. Ini adalah cara yang paling direkomendasikan untuk melakukannyaremoveObservers:self
dealloc
metode ini di iOS 6?Jawaban:
Jawaban umumnya adalah "segera setelah Anda tidak lagi membutuhkan notifikasi". Ini jelas bukan jawaban yang memuaskan.
Saya akan merekomendasikan, bahwa Anda menambahkan panggilan
[notificationCenter removeObserver: self]
dalam metodedealloc
kelas-kelas itu, yang ingin Anda gunakan sebagai pengamat, karena ini adalah kesempatan terakhir untuk membatalkan pendaftaran pengamat dengan rapi. Namun, ini hanya akan melindungi Anda dari crash karena pusat notifikasi memberi tahu benda mati. Itu tidak dapat melindungi kode Anda dari menerima pemberitahuan, ketika objek Anda belum / tidak lagi dalam keadaan di mana mereka dapat menangani pemberitahuan dengan benar. Untuk ini ... Lihat di atas.Sunting (karena jawabannya tampaknya menarik lebih banyak komentar daripada yang saya kira) Yang ingin saya katakan di sini adalah: sangat sulit untuk memberikan nasihat umum tentang kapan waktu terbaik untuk menghapus pengamat dari pusat pemberitahuan, karena itu tergantung:
Jadi, saran umum terbaik yang bisa saya berikan: untuk melindungi aplikasi Anda. terhadap setidaknya satu kemungkinan kegagalan, lakukan
removeObserver:
tariannyadealloc
, karena itulah titik terakhir (dalam kehidupan objek), di mana Anda dapat melakukannya dengan rapi. Ini tidak berarti: "cukup tunda penghapusan sampaidealloc
dipanggil, dan semuanya akan baik-baik saja". Sebagai gantinya, hapus pengamat segera setelah objek tidak lagi siap (atau diperlukan) untuk menerima notifikasi . Itu adalah momen yang tepat. Sayangnya, karena tidak mengetahui jawaban atas semua pertanyaan yang disebutkan di atas, saya bahkan tidak dapat menebak, kapan saat itu akan tiba.Anda selalu dapat dengan aman
removeObserver:
suatu objek beberapa kali (dan semua kecuali panggilan pertama dengan pengamat tertentu akan menjadi nops). Jadi: pikirkan untuk melakukannya (lagi)dealloc
hanya untuk memastikan, tetapi yang pertama dan terpenting: lakukan pada saat yang tepat (yang ditentukan oleh kasus penggunaan Anda).sumber
dealloc
hanyalah garis pertahanan terakhir agar aplikasi tidak mogok karena nantinya akses ke objek yang telah didekalokasi. Tetapi tempat yang tepat untuk membatalkan pendaftaran pengamat biasanya di tempat lain (dan seringkali, jauh lebih awal dalam siklus hidup objek). Saya tidak mencoba untuk mengatakan di sini "Hei, lakukan sajadealloc
dan semuanya akan baik-baik saja".viewWillDisappear
" Masalah dengan memberikan saran konkret adalah, hal itu sangat bergantung pada jenis objek yang Anda daftarkan sebagai pengamat untuk jenis acara apa. Ini mungkin solusi yang tepat untuk membatalkan pendaftaran pengamat diviewWillDisappear
(atauviewDidUnload
) untukUIViewController
s, tetapi itu benar-benar tergantung pada kasus penggunaan.Catatan: Ini telah diuji dan berfungsi 100% persen
Cepat
PresentedViewController
Objective-C
Dalam hal
iOS 6.0 > version
, lebih baik untuk menghapus pengamatviewWillDisappear
karenaviewDidUnload
metode tidak digunakan lagi.Ada banyak kali lebih baik
remove observer
bila tampilan telah dihapus darinavigation stack or hierarchy
.PresentedViewController
sumber
viewWillAppear:
removeObserver:self
di salah satuUIViewController
acara siklus hidup hampir pasti akan merusak minggu Anda. Bacaan lebih lanjut: subyektif-objek-c.blogspot.com/2011/04/…removeObserver
panggilanviewWillDisappear
seperti yang ditunjukkan jelas merupakan cara yang tepat untuk pergi jika pengontrol disajikan melaluipushViewController
. Jika Anda memasukkannya,dealloc
makadealloc
tidak akan pernah dipanggil - setidaknya menurut pengalaman saya ...Sejak iOS 9, tidak perlu lagi menghapus pengamat.
https://developer.apple.com/library/mac/releasenotes/Foundation/RN-Foundation/index.html#10_11NotificationCenter
sumber
Jika pengamat ditambahkan ke pengontrol tampilan , saya sangat menyarankan untuk menambahkan
viewWillAppear
dan menghapusnyaviewWillDisappear
.sumber
viewWillAppear
danviewWillDisappear
untuk viewControllers?dealloc
panggilan segera. Kembali ke pengontrol tampilan kemudian dapat menyebabkan beberapa pemberitahuan jika pengamat ditambahkan dalam perintah inisialisasi.sumber
self
setelah[super dealloc]
membuat saya gugup ... (bahkan jika penerima tidak mungkin benar-benar membedakan penunjuk dengan cara apa pun, Anda tidak pernah tahu, bagaimana penerapannyaNSNotificationCenter
)[super dealloc]
harus selalu menjadi pernyataan terakhir daridealloc
metode Anda . Ini menghancurkan objek Anda; setelah dijalankan, Anda tidak memiliki validself
lagi. / cc @Dirk[super dealloc]
tidak diperlukan lagiSecara umum saya memasukkannya ke dalam
dealloc
metode.sumber
Dalam penggunaan cepat deinit karena dealloc tidak tersedia:
Dokumentasi cepat:
sumber
* edit: Saran ini berlaku untuk iOS <= 5 (bahkan di sana Anda harus menambahkan
viewWillAppear
dan menghapusviewWillDisappear
- namun saran tersebut berlaku jika karena alasan tertentu Anda telah menambahkan pengamatviewDidLoad
)Jika Anda telah menambahkan pengamat di
viewDidLoad
Anda harus menghapusnya di keduadealloc
danviewDidUnload
. Jika tidak, Anda akan menambahkannya dua kali saatviewDidLoad
dipanggil setelahnyaviewDidUnload
(ini akan terjadi setelah peringatan memori). Ini tidak diperlukan di iOS 6 yangviewDidUnload
sudah tidak digunakan lagi dan tidak akan dipanggil (karena tampilan tidak lagi otomatis diturunkan).sumber
Menurut pendapat saya, kode berikut tidak masuk akal di ARC :
Di iOS 6 , juga tidak ada gunanya menghapus pengamat
viewDidUnload
, karena sekarang sudah tidak digunakan lagi.Singkatnya, saya selalu melakukannya
viewDidDisappear
. Namun, itu juga tergantung pada kebutuhan Anda, seperti yang dikatakan @Dirk.sumber
Saya rasa saya menemukan jawaban yang dapat diandalkan ! Saya harus melakukannya, karena jawaban di atas ambigu dan tampak bertentangan. Saya melihat-lihat Buku Masakan dan Panduan Pemrograman.
Pertama, gaya
addObserver:
dalamviewWillAppear:
danremoveObserver:
dalamviewWillDisappear:
tidak berfungsi untuk saya (saya mengujinya) karena saya memposting pemberitahuan di pengontrol tampilan anak untuk mengeksekusi kode di pengontrol tampilan induk. Saya hanya akan menggunakan gaya ini jika saya memposting dan mendengarkan notifikasi dalam pengontrol tampilan yang sama.Jawaban yang paling saya andalkan, saya temukan di Pemrograman iOS: Big Nerd Ranch Guide 4th. Saya mempercayai orang-orang BNR karena mereka memiliki pusat pelatihan iOS dan mereka tidak hanya menulis buku masak lain. Mungkin demi kepentingan terbaik mereka agar akurat.
BNR contoh satu:
addObserver:
ininit:
,removeObserver:
indealloc:
BNR contoh dua:
addObserver:
inawakeFromNib:
,removeObserver:
indealloc:
… Saat menghapus pengamat di dalamnya
dealloc:
tidak digunakan[super dealloc];
Saya harap ini membantu orang berikutnya ...
Saya memperbarui posting ini karena Apple sekarang hampir sepenuhnya hilang dengan Storyboards sehingga hal yang disebutkan di atas mungkin tidak berlaku untuk semua situasi. Yang penting (dan alasan saya menambahkan posting ini di tempat pertama) adalah memperhatikan jika Anda
viewWillDisappear:
dipanggil. Bukan untuk saya ketika aplikasi memasuki latar belakang.sumber
Jawaban yang diterima tidak aman dan dapat menyebabkan kebocoran memori. Harap jangan tinggalkan unregister di dealloc tetapi juga batalkan pendaftaran di viewWillDisappear (tentu saja jika Anda mendaftar di viewWillAppear) .... ITU APA YANG SAYA LAKUKAN TAPI DAN BEKERJA HEBAT! :)
sumber
Penting untuk diperhatikan juga bahwa
viewWillDisappear
yang dipanggil juga saat pengontrol tampilan menyajikan UIView baru. Delegasi ini hanya menunjukkan bahwa tampilan utama pengontrol tampilan tidak terlihat di layar.Dalam kasus ini,
viewWillDisappear
membatalkan alokasi notifikasi mungkin merepotkan jika kami menggunakan notifikasi untuk memungkinkan UIview berkomunikasi dengan pengontrol tampilan induk.Sebagai solusi, saya biasanya menghapus pengamat dalam salah satu dari dua metode ini:
Untuk alasan serupa, ketika saya mengeluarkan notifikasi pertama kali, saya perlu memperhitungkan fakta bahwa setiap kali tampilan dengan muncul di atas pengontrol maka
viewWillAppear
metode dipecat. Ini pada gilirannya akan menghasilkan banyak salinan dari pemberitahuan yang sama. Karena tidak ada cara untuk memeriksa apakah pemberitahuan sudah aktif, saya mengatasi masalah dengan menghapus pemberitahuan sebelum menambahkannya:sumber
SWIFT 3
Ada dua kasus penggunaan notifikasi: - notifikasi diperlukan hanya saat pengontrol tampilan ada di layar; - mereka selalu dibutuhkan, bahkan jika pengguna membuka layar lain melalui arus.
Untuk kasus pertama tempat yang tepat untuk menambah dan menghapus pengamat adalah:
untuk kasus kedua cara yang benar adalah:
Dan tidak pernah menaruh
removeObserver
dideinit{ ... }
- itu KESALAHAN sebuah!sumber
sumber