ViewController respondsToSelector: pesan dikirim ke instance yang dibatalkan alokasinya (CRASH)

95

Oke, ini kesepakatannya, saya benci mengajukan pertanyaan tentang debugging dan crash saya. Karena saya biasanya menanganinya sendiri, tetapi saya tidak bisa mengatasi hal ini, bahkan setelah melihat beberapa pertanyaan .

Oke jadi inilah masalahnya, saya menemukan aplikasi saya secara acak dan mati dengan pelacakan tumpukan ini:

*** -[ViewController respondsToSelector:]: message sent to deallocated instance 0x1e5d2ef0

Di mana ViewControllerdapat bervariasi, kadang-kadang tempat di mana kode saya mogok, TIDAK memiliki relevansi dengan hal itu ViewControllerdan tidak memiliki atau menyebutnya.

Juga, untuk mendapatkan jejak konsol itu, saya telah mengaktifkan Zombies, jika tidak saya tidak akan mendapatkan cetakan konsol sama sekali, saya hanya akan mendapatkan:, objc_msgSendyang saya tahu berarti saya mengirim pesan sesuatu yang dirilis. Tetapi saya tidak dapat menemukan di mana itu ... Saya benar-benar terjebak! Biasanya saya selalu men-debug kerusakan saya, jadi saya benar-benar terjebak dalam hal ini.

Sekali lagi, ini crash di tempat yang berbeda pada waktu yang berbeda, on dan off. Dan tempat terjadinya crash hampir tidak ada relevansinya dengan ViewController. Dan menurut saya ini sangat membingungkan.

Apakah Anda memerlukan kode saya? Saya memiliki banyak file dan karena macet di berbagai tempat, mendistribusikan kode saya akan berantakan!

Saya telah mencoba menambahkan breakpoint simbolis tetapi tidak berhasil, dan Zombies tidak tersedia di aplikasi Instrumen untuk iOS. Saya tidak dapat menjalankan aplikasi saya di simulator karena memiliki kerangka kerja arsitektur yang tidak mendukung.

Terimakasih semuanya...

MCKapur.dll
sumber
apakah Anda melihat pertanyaan ini: stackoverflow.com/questions/1585688/…
self
Dengan asumsi cara Anda bertransisi ke tampilan Anda konsisten, mungkin Anda dapat menunjukkan satu atau dua contoh kepada kami. Jika Anda melakukan panggilan push / presentViewController standar, Anda seharusnya baik-baik saja, tetapi saya melihat banyak orang di sini melakukan hal-hal seperti mengalokasikan / menginit pengontrol tampilan, tetapi kemudian tidak melakukan push / present, melainkan hanya menambahkan pengontrol lihat sebagai subview. Hanya contoh acak. Tetapi kami tidak dapat mendiagnosis ini tanpa beberapa kode. Semoga beberapa cuplikan akan membantu kami mengetahui apa yang terjadi, jadi mari kita lihat.
Rob
Bagaimana dengan mengaktifkan titik putus simbolik? Coba tambahkan ini: wiki.zemingo.com/index.php?title=Symbolic_Breakpoints
Stavash
@RobertRyan Saya menggunakan presentModalViewController, saya tidak menambahkannya sebagai subview
MCKapur
Dalam kasus saya, pengontrol tampilan anak saya berisi webView, dan anak VC adalah delegasi untuk scrollView webView. Saya perlu menghapus referensi delegasi secara manual selama dealloc / viewWillDisappear atau saya mengalami error ini. Semoga bisa membantu seseorang.
Dermot

Jawaban:

169

Gunakan Instrumen untuk melacak kesalahan instance yang dibatalkan alokasinya. Profil aplikasi Anda ( Cmd ⌘+ I) dan pilih template Zombies . Setelah aplikasi Anda berjalan, coba hancurkan. Anda harus mendapatkan sesuatu seperti itu:

masukkan deskripsi gambar di sini

Klik panah di sebelah alamat di popover untuk menampilkan objek yang dipanggil setelah dialokasikan.

masukkan deskripsi gambar di sini

Anda harus melihat sekarang setiap panggilan yang telah mengubah jumlah tetap dari objek ini. Ini bisa jadi karena mengirim pesan pertahankan / rilis secara langsung serta menguras kumpulan rilis otomatis atau menyisipkan ke dalam NSArays.

Kolom RefCt menunjukkan retretCount setelah tindakan dipanggil dan Penelepon yang Bertanggung Jawab menunjukkan nama kelas dan metode yang digunakan untuk melakukannya. Ketika Anda mengklik dua kali pada retensi / rilis, instrumen akan menunjukkan kepada Anda baris kode di mana ini dilakukan (Jika ini tidak berfungsi, Anda dapat memeriksa panggilan dengan memilihnya dan memilih mitranya di panel Detail Diperluas ):

masukkan deskripsi gambar di sini

Ini akan membiarkan Anda memeriksa semua daur hidup objek retretCount dan mungkin Anda akan segera menemukan masalah Anda. Semua harus Anda lakukan adalah menemukan hilang mempertahankan untuk terbaru rilis .

Johnnywho
sumber
3
Masalahnya mungkin bukan yang terbaru release, secara spesifik. Masalahnya adalah setiap tidak seimbang release. Saya juga bisa menjadi kegagalan untuk retainsesuatu yang Anda simpan petunjuknya dan rujuk nanti.
Ken Thomases
1
Selain itu, saya tidak memiliki template instrumen Zombie, itu mungkin karena saya menggunakan Xcode Beta 4.5, sementara itu saya akan beralih ke 4.4
MCKapur
2
Oh, Zombie hanya tersedia di simulator iOS. SAYA TIDAK DAPAT menjalankan simulator iOS, beberapa framework dan pustaka yang saya gunakan tidak mendukung arsitektur
MCKapur
Hanya catatan kecil. Ini dari apa yang baru di xcode 5. "Template instrumen Zombies telah ditingkatkan di Xcode 5 dan sekarang mendukung penggunaan di perangkat. Menggunakan Zombies di perangkat memerlukan iOS 7." Catatan ini dibawakan oleh saya dan 2 jam waktu saya yang berharga ...
nickfox
2
Apa artinya jika Aplikasi kita berhenti mogok dan berhenti memberikan kesalahan "pesan dikirim ke contoh yang dibatalkan alokasinya" saat kita mengaitkan instrumen ini ke sana? (Seolah-olah "penyakit" menghilang ketika pasien diberi "tes diagnostik.")
Praxiteles
59

punya masalah serupa. Dalam kasus saya, viewController perlu mendapatkan peristiwa navigationController, jadi ia mendaftar sebagai delegasi pengontrol navigasi:

 self.navigationController.delegate = self;

Crash terjadi ketika pengontrol tersebut dibatalkan alokasinya tetapi masih menjadi delegasi untuk pengontrol tampilan. Menambahkan kode ini di dealloc tidak berpengaruh:

-(void) dealloc
{
    if (self.navigationController.delegate == self)
    {
        self.navigationController.delegate = nil;
    }

karena pada saat dealloc dipanggil, pengontrol tampilan telah dihapus dari hierarki tampilan, jadi self.navigationController nihil, jadi perbandingannya dijamin gagal! :-(

Solusinya adalah menambahkan kode ini untuk mendeteksi VC yang meninggalkan hierarki tampilan sebelum ia benar-benar melakukannya. Ini menggunakan metode yang diperkenalkan di iOS 5 untuk menentukan kapan tampilan dimunculkan dan tidak didorong

-(void) viewWillDisappear:(BOOL) animated
{  
   [super viewWillDisappear:animated];
   if ([self isMovingFromParentViewController])
   {
      if (self.navigationController.delegate == self)
      {
           self.navigationController.delegate = nil;
      }
   }
}

Tidak ada lagi crash!

perangkat lunak berevolusi
sumber
Saya juga terima kasih - hanya 4 jam pencarian yang diperlukan untuk menemukan posting ini.
daidai
Terima kasih telah memposting, memiliki masalah yang sama ^^
Tyron
Bagaimana Anda menemukan solusi untuk masalah yang menjengkelkan seperti itu? Hormat !!
ViruMax
4

Bagi siapa pun yang tidak bisa menyelesaikannya, berikut beberapa teknik lainnya:

https://stackoverflow.com/a/12264647/539149

https://stackoverflow.com/a/5698635/539149

https://stackoverflow.com/a/9359792/539149

https://stackoverflow.com/a/15270549/539149

https://stackoverflow.com/a/12098735/539149

Anda dapat menjalankan Instrumen di Xcode 5 dengan mengklik popup proyek-> Edit Skema ... Profil -> Instrumen dan pilih Alokasi atau Kebocoran, lalu buat profil aplikasi Anda, lalu hentikan Instrumen, klik tombol info di Alokasi dan "Aktifkan Deteksi NSZombie" .

Namun, untuk pesan yang datang langsung dari com.apple.main-thread, ini mungkin tidak akan mengungkapkan apa pun.

Saya membenturkan kepala saya pada ini selama lebih dari dua jam dan jawabannya ternyata adalah rilis berlebihan, yang saya temukan dengan mengomentari salinan proyek saya dengan kekerasan sampai saya menemukan pelakunya:

[viewController release];
viewController = NULL;

Masalahnya adalah rilis tidak menyetel variabel ke NULL.

Itu berarti bahwa menyetelnya ke panggilan NULL rilis lagi, mengurangi refcount dan mengosongkan memori segera sampai nanti ketika variabel yang mereferensikan viewController selesai dengannya.

Jadi, aktifkan ARC atau pastikan proyek Anda secara konsisten menggunakan rilis atau NULL tetapi tidak keduanya. Preferensi saya adalah menggunakan NULL karena dengan demikian tidak ada peluang untuk mereferensikan zombie tetapi itu membuat menemukan di mana objek dilepaskan lebih sulit.

Zack Morris
sumber
4

Saya telah menemui masalah yang sama di iOS kemarin. Saya telah membuat IAP di subview "Tentang" Aplikasi, dan saya telah menambahkan Pengamat Transaksi di "Tentang" viewDidLoad. Ketika saya membeli untuk pertama kalinya, tidak ada masalah, tetapi setelah saya kembali ke jendela utama dan masuk tentang subview untuk membeli lagi, masalah "pesan dikirim ke contoh yang dibatalkan alokasinya" terjadi, dan Aplikasi macet.

- (void)viewDidLoad
{
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];                                           object:nil];
}

Setelah saya menghapus Transaction Observer di dealloc, masalah terpecahkan.

- (void)dealloc
{
    // Even though we are using ARC, we still need to manually stop observing any
    // NSNotificationCenter notifications.  Otherwise we could get "zombie" crashes when
    // NSNotificationCenter tries to notify us after our -dealloc finished.

    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
Ouyang Yong
sumber
Itu memperbaiki crash runtime saya ... Saya mendapatkan zombieobjek untuk pembelian inApp. Setelah berjam-jam menggali, saya menemukan yang satu ini .... A BIG THANKS Man.
Mahendra
4

Saya memiliki masalah yang sangat mirip dan saya tahu itu karena set delegasi pengontrol navigasi.

Di bawah ini memecahkan masalah saya,

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if (self.navigationController.delegate != self) {
        self.navigationController.delegate = self;
    }
}

-(void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    if (self.navigationController.delegate == self) {
        self.navigationController.delegate = nil;
    }
}
thatzprem.dll
sumber
Terima kasih!! masalah yang sama di sini.
pegpeg
2

Punya masalah yang sama di OS X.

Untuk mengatasi - (void)deallocmetode ini tidak cukup seperti yang sudah dikatakan @SoftwareEvolved. Namun sayangnya - (void)viewWillDisappearhanya tersedia pada versi 10.10 dan yang lebih baru.

Saya memperkenalkan metode kustom di subkelas NSViewController saya di mana mengatur semua referensi berbahaya-zombie menjadi nihil. Dalam kasus saya, itu adalah NSTableViewproperti ( delegatedan dataSource).

- (void)shutdown
{
  self.tableView.delegate = nil;
  self.tableView.dataSource = nil;
}

Itu saja. Setiap kali saya akan menghapus tampilan dari superview perlu memanggil metode ini.

Astoria
sumber
2

Saya memiliki masalah yang sama. Sulit untuk menemukan masalah penyebab delegasi mana, karena tidak menunjukkan pernyataan baris atau kode apa pun Jadi saya telah mencoba beberapa cara, Mungkin ini akan membantu Anda.

  1. Buka file xib dan dari pemilik file, Pilih menu sebelah kanan "show the connection inspector". Delegasi dicantumkan, setel ke nihil yang dicurigai.
  2. (Sama seperti kasus saya) Objek Properti seperti Textfield dapat menimbulkan masalah, Jadi setel delegasinya ke nihil.
-(void) viewWillDisappear:(BOOL) animated{

[super viewWillDisappear:animated];

if ([self isMovingFromParentViewController]){

self.countryTextField.delegate = nil;

self.stateTextField.delegate = nil;

}

}
Nadim
sumber