jika Anda memberi tahu objek c objektif untuk removeObservers: untuk lintasan kunci dan lintasan kunci itu belum terdaftar, itu akan memecahkan sads. Suka -
'Tidak dapat menghapus pengamat untuk jalur kunci "theKeyPath" dari karena tidak terdaftar sebagai pengamat.'
apakah ada cara untuk menentukan apakah suatu objek memiliki pengamat terdaftar, jadi saya bisa melakukan ini
if (object has observer){
remove observer
}
else{
go on my merry way
}
objective-c
cocoa
key
key-value-observing
Aran Mulholland
sumber
sumber
addObserver:
dalamviewWillAppear:
dan SejalanremoveObserver:
diviewWillDisappear:
, panggilan yang benar dipasangkan. Saya harus membuat perbaikan cepat jadi saya akan mengimplementasikan solusi try-catch dan meninggalkan komentar untuk menyelidiki penyebabnya lebih lanjut.Jawaban:
Cobalah menangkap panggilan removeObserver Anda
sumber
Pertanyaan sebenarnya adalah mengapa Anda tidak tahu apakah Anda mengamatinya atau tidak.
Jika Anda melakukan ini di kelas objek yang diamati, berhenti. Apa pun yang mengamatinya berharap untuk terus mengamatinya. Jika Anda memotong notifikasi pengamat tanpa sepengetahuannya, mengharapkan hal-hal akan rusak; lebih khusus, berharap kondisi pengamat basi karena tidak menerima pembaruan dari objek yang sebelumnya diamati.
Jika Anda melakukan ini di kelas objek pengamatan, cukup ingat objek mana yang Anda amati (atau, jika Anda hanya mengamati satu objek, apakah Anda mengamatinya). Ini mengasumsikan bahwa pengamatan itu dinamis dan antara dua objek yang tidak berhubungan; jika pengamat memiliki yang diamati, cukup tambahkan pengamat setelah Anda membuat atau menyimpan yang diamati, dan lepaskan pengamat sebelum Anda melepaskan yang diamati.
Menambah dan menghapus objek sebagai pengamat biasanya terjadi di kelas pengamat, dan tidak pernah di objek yang diamati.
sumber
FWIW,
[someObject observationInfo]
tampaknyanil
jikasomeObject
tidak memiliki pengamat. Saya tidak akan mempercayai perilaku ini, karena saya belum melihatnya didokumentasikan. Juga, saya tidak tahu cara membacaobservationInfo
untuk mendapatkan pengamat tertentu.sumber
objectAtIndex:
tidak menghasilkan hasil yang diinginkan.)NSKeyValueObserving.h
Satu-satunya cara untuk melakukan ini adalah dengan menetapkan bendera ketika Anda menambahkan pengamat.
sumber
Saat Anda menambahkan pengamat ke objek Anda bisa menambahkannya ke
NSMutableArray
seperti ini:Jika Anda ingin menghapus objek, Anda dapat melakukan sesuatu seperti:
Ingat, jika Anda tidak melihat satu objek menghapusnya dari
_observedObjects
array:sumber
NSHashTable
/NSMapTable
untuk menyimpan referensi yang lemah.Menurut pendapat saya - ini bekerja mirip dengan mekanisme retainCount. Anda tidak dapat memastikan bahwa saat ini Anda memiliki pengamat. Bahkan jika Anda memeriksa: self.observationInfo - Anda tidak dapat mengetahui dengan pasti bahwa Anda akan memiliki / tidak akan memiliki pengamat di masa mendatang.
Seperti retainCount . Mungkin metode observasiInfo bukan jenis yang tidak berguna, tapi saya hanya menggunakannya untuk keperluan debug.
Jadi sebagai hasilnya - Anda hanya perlu melakukannya seperti dalam manajemen memori. Jika Anda menambahkan pengamat - hapus saja ketika Anda tidak membutuhkannya. Seperti menggunakan metode viewWillAppear / viewWillDisappear dll. Misalnya:
Dan Anda membutuhkan beberapa pemeriksaan khusus - mengimplementasikan kelas Anda sendiri yang menangani berbagai pengamat dan menggunakannya untuk pemeriksaan Anda.
sumber
[self removeObserver:nil forKeyPath:@""];
perlu pergi sebelum:[super viewWillDisappear:animated];
- (void) setupSomething { [super setupSomething]; … } - (void) tearDownSomething { … [super tearDownSomething]; }
[someObject observationInfo]
kembalinil
jika tidak ada pengamat.sumber
Inti dari pola pengamat adalah untuk memungkinkan kelas yang diamati "disegel" - untuk tidak tahu atau peduli apakah itu sedang diamati. Anda secara eksplisit mencoba untuk mematahkan pola ini.
Mengapa?
Masalah yang Anda hadapi adalah Anda berasumsi sedang diamati padahal sebenarnya tidak. Objek ini tidak memulai pengamatan. Jika Anda ingin kelas Anda memiliki kendali atas proses ini, maka Anda harus mempertimbangkan untuk menggunakan pusat notifikasi. Dengan begitu kelas Anda memiliki kontrol penuh kapan data dapat diamati. Karena itu, tidak peduli siapa yang menonton.
sumber
Saya bukan penggemar yang mencoba menangkap solusi jadi apa yang saya lakukan sebagian besar waktu adalah bahwa saya membuat metode berlangganan dan berhenti berlangganan untuk pemberitahuan khusus di dalam kelas itu. Misalnya dua metode ini berlangganan atau berhenti berlangganan objek ke notifikasi keyboard global:
Di dalam metode itu saya menggunakan properti pribadi yang disetel ke benar atau salah, bergantung pada status berlangganan seperti:
sumber
Selain jawaban Adam saya ingin menyarankan untuk menggunakan makro seperti ini
contoh penggunaan
sumber