Galat “pemilih yang tidak dikenal dikirim ke instance” di Objective-C

155

Saya membuat tombol dan menambahkan tindakan untuk itu, tetapi segera setelah dipanggil, saya mendapatkan kesalahan ini:

-[NSCFDictionary numberButtonClick:]: unrecognized selector sent to instance
 0x3d03ac0 2010-03-16 22:23:58.811
 Money[8056:207] *** Terminating app
 due to uncaught exception
 'NSInvalidArgumentException', reason:'*** -[NSCFDictionary numberButtonClick:]:  unrecognized selector sent to instance 0x3d03ac0'

Ini kode saya:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        UIButton *numberButton = [UIButton buttonWithType:UIButtonTypeCustom];        
        numberButton.frame = CGRectMake(10, 435, 46, 38);
        [numberButton setImage:[UIImage imageNamed:@"one.png"] forState:UIControlStateNormal];
        [numberButton addTarget:self action:@selector(numberButtonClick:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview: numberButton]; 
    }
return self;
}

-(IBAction)numberButtonClick:(id)sender{
    NSLog(@"---");
}
Halo Dunia
sumber

Jawaban:

187

Sepertinya Anda tidak mengelola memori view controller dengan benar dan sedang tidak dialokasikan pada beberapa titik - yang menyebabkan numberButtonClicked:metode dikirim ke objek lain yang sekarang menempati memori yang sebelumnya ditempati oleh controller tampilan ...

Pastikan Anda mempertahankan / melepaskan pengontrol tampilan dengan benar.

Jasarien
sumber
105
Itu diagnosis yang sangat cerdik dari beberapa baris kode.
Michael Morrison
41
OK, jadi masalah teridentifikasi ... tetapi "Pastikan Anda mempertahankan / melepaskan pengontrol tampilan Anda dengan benar." adalah saran, bukan solusi.
Alex Gray
12
@ alex grey, Apa? Manajemen memori yang tepat pada pengontrol tampilan memecahkan masalah ... Saya tidak mengerti bagaimana itu bukan solusi?
Jasarien
28
benar. meskipun ini tampaknya menjadi "perbaikan" .. dan saya mungkin berada di minoritas, (meskipun saya masih berhasil ada), tetapi hubungan antara masalah dan solusinya tidak segera jelas. misalnya, saya temui -[NSWindow end]: unrecognized selector sent to instance 0x100523e80 dan meskipun saya menyadari kesamaan dengan OP, dan bahkan mungkin penyebab masalah dari jawaban Anda, implementasi perbaikan tidak segera jelas
Alex Gray
12
Segera jelas. Manajemen memori NSWindow Anda tidak benar di suatu tempat di sepanjang jalur. Pergi melalui siklus hidup itu dan memperbaikinya.
Jasarien
127

Bagi mereka yang datang ke sini melalui Google seperti yang saya lakukan, yang mungkin lebih berkaitan dengan Xcode 4.2 + / iOS 5+ lebih, apa dengan ARC. Saya memiliki kesalahan yang sama " pemilih yang tidak dikenal dikirim ke instance ". Dalam kasus saya, saya memiliki tindakan target UIButton diatur untuk lulus sendiri sebagai parameter pengirim, tetapi kemudian menyadari bahwa saya tidak membutuhkannya dan menghapusnya dalam kode. Jadi, sesuatu seperti:

- (IBAction)buttonPressed:(UIButton *)sender {

Diubah menjadi:

- (IBAction)buttonPressed {

Mengklik kanan UIButton yang dipermasalahkan menunjukkan bahwa acara Touch Up Inside dikaitkan dengan tombol pengendali tampilanTekan: metode. Menghapus ini dan menugaskannya kembali ke metode yang dimodifikasi berhasil memperlakukan.

LeonardChallis
sumber
Ini sangat membantu, meskipun saya pikir pertanyaan dan tanggapannya sendiri akan membuatnya lebih mudah ditemukan.
Curtis Inderwiesche
@LeonardChallis Bagaimana Anda bisa mereferensikan pengirim di tombolTekan jika tidak dilewatkan sebagai parameter?
zakdances
8
Respon yang sangat membantu. Saya baru saja mengalami masalah ini dan solusi Anda benar. Mengikuti kelas iOS Stanford di iTunesU ketika ini terjadi. Sekali lagi terima kasih atas jawaban Anda!
Marshall Alsup
1
@LeonardChallis Terima kasih. Saya menambahkan jawaban gratis untuk jawaban Anda.
1.21 gigawatt
1
Saya hanya berjuang dengan masalah yang sama, menghapus parameter pengirim dari fungsi pemilih, dan kemudian bertanya-tanya bagaimana cara mendapatkan pengirim. Dalam kasus saya, saya mendapatkan kesalahan karena saya lupa untuk meletakkan titik dua setelah panggilan balik pemilih, sehingga menyebabkan ketidaksesuaian urutan panggilan. Dengan titik dua, saya dapat menyimpan argumen pengirim.
74

Ini adalah jawaban Google teratas untuk masalah ini, tetapi saya memiliki penyebab / hasil yang berbeda - saya pikir saya akan menambahkan dua sen saya seandainya orang lain menemukan masalah ini.

Saya memiliki masalah serupa pagi ini. Saya menemukan bahwa jika Anda mengklik kanan item UI yang memberi Anda masalah, Anda dapat melihat koneksi apa yang telah dibuat. Dalam kasus saya, saya memiliki tombol yang terhubung ke dua tindakan. Saya menghapus tindakan dari menu klik kanan dan mengembalikannya dan masalah saya diperbaiki.

Jadi, pastikan tindakan Anda terhubung dengan benar.

Chris K
sumber
Ini masalah saya. Saya mengganti nama suatu fungsi dan mengubah kode saya tetapi tidak mengubah koneksi dalam file xib.
BFTrick
2
TERIMA KASIH! Ternyata saya punya tiga metode yang saya hapus masih direferensikan. Menggangguku selama seminggu!
erdekhayser
25

OK, saya harus chip di sini. OP secara dinamis menciptakan tombol . Saya memiliki masalah yang sama dan jawabannya (setelah jam berburu) sangat sederhana sehingga membuat saya sakit.

Ketika menggunakan:

action:@selector(xxxButtonClick:)

or (as in my case)

action:NSSelectorFromString([[NSString alloc] initWithFormat:@"%@BtnTui:", name.lowercaseString])

Jika Anda menempatkan tanda titik dua di ujung string - itu akan melewati pengirim. Jika Anda tidak meletakkan titik dua di bagian akhir string, maka tidak akan, dan penerima akan mendapatkan kesalahan jika mengharapkannya. Sangat mudah untuk kehilangan titik dua jika Anda secara dinamis membuat nama acara.

Opsi kode penerima terlihat seperti ini:

- (void)doneBtnTui:(id)sender {
  NSLog(@"Done Button - with sender");
}
 or
- (void)doneBtnTui {
  NSLog(@"Done Button - no sender");
}

Seperti biasa, selalu merupakan jawaban yang jelas terlewatkan.

Craig H.
sumber
1
Terima kasih banyak! Ini adalah masalah saya (tidak meletakkan tanda titik dua ':' di akhir nama pemilih). Kenapa hampir selalu hal-hal sederhana yang paling bodoh yang membuat kita Geeks membenturkan kepala kita ke dinding pukul 3 pagi? Terima kasih sekali!
TWright
23

Dalam kasus saya, fungsinya tidak mengharapkan argumen tetapi tombol telah dikonfigurasi untuk mengirim satu yang menyebabkan kesalahan. Untuk memperbaiki ini saya harus me-rewire event handler.

Inilah fungsi saya:

masukkan deskripsi gambar di sini

Perhatikan itu tidak mengandung argumen.

Ini adalah gambar konfigurasi tombol saya (klik kanan pada tombol untuk melihatnya):

masukkan deskripsi gambar di sini

Perhatikan ada 3 penangan acara.

Untuk memperbaikinya, saya harus menghapus masing-masing item acara karena salah satunya mengirim referensi ke dirinya sendiri ke fungsi EnterPressed. Untuk menghapus item-item ini, saya mengklik ikon x kecil di sebelah nama setiap item sampai tidak ada item yang ditampilkan.

masukkan deskripsi gambar di sini

Selanjutnya saya harus menghubungkan kembali tombol ke acara tersebut. Untuk melakukan ini, tahan tombol Control dan kemudian tarik garis dari tombol ke tindakan. Itu harus mengatakan "Hubungkan Aksi". Catatan: Saya harus me-restart XCode agar ini berfungsi karena beberapa alasan; jika tidak, biarkan saya menyisipkan tindakan (alias membuat tindakan baru) di atas atau di bawah fungsi.

masukkan deskripsi gambar di sini

Anda sekarang harus memiliki penangan event tunggal ditransfer ke acara tombol yang tidak melewati argumen:

masukkan deskripsi gambar di sini

Jawaban ini memuji jawaban oleh @Leonard Challis yang harus Anda baca juga.

1,21 gigawatt
sumber
14

Ini juga bisa terjadi jika Anda tidak mengatur "Kelas" dari tampilan dalam pembangun antarmuka.

pengguna1658373
sumber
Agh terima kasih! Ini menyebabkan aplikasi saya mogok di segue, hanya lupa untuk mengatur kelas controller.
Eichhörnchen
Mengapa perlu mengetahui kelas? Saya mencoba menggunakan UITableViewSection sebagai UIView, dan saya mendapatkan kesalahan ini. Compiler mengatakan bahwa UITableViewSection tidak ada, jadi saya anggap internal untuk UIKit.
Ian Warburton
13

Dalam kasus saya, saya menggunakan NSNotificationCenter dan berusaha menggunakan pemilih yang tidak mengambil argumen, tetapi menambahkan titik dua. Menghapus usus besar memperbaiki masalah.

Saat menggunakan nama pemilih, jangan gunakan tanda titik dua jika tidak ada argumen. Jika ada satu argumen, gunakan satu tanda titik dua. Jika ada lebih dari satu argumen, Anda harus menamainya bersama dengan tanda titik dua untuk setiap argumen.

Lihat jawaban Adam Rosenfield di sini: Selektor di Objective-C?

Nathan Garabedian
sumber
11

Saya punya masalah dengan proyek Swift di mana saya membuat tombol secara dinamis. Kode masalah:

var trashBarButtonItem: UIBarButtonItem {
    return UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "newButtonClicked")
}

func newButtonClicked(barButtonItem: UIBarButtonItem) {
    NSLog("A bar button item on the default toolbar was clicked: \(barButtonItem).")
}

Solusinya adalah dengan menambahkan titik dua penuh ':' setelah tindakan: mis

var trashBarButtonItem: UIBarButtonItem {
        return UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "newButtonClicked:")
    }

    func newButtonClicked(barButtonItem: UIBarButtonItem) {
        NSLog("A bar button item on the default toolbar was clicked: \(barButtonItem).")
    }

Contoh lengkap di sini: https://developer.apple.com/library/content/samplecode/UICatalog/Listings/Swift_UIKitCatalog_DefaultToolbarViewController_swift.html

FredL
sumber
Hanya setelah mengikuti tutorial dan membaca petunjuk tentang masalah yang sama persis ini - saya jatuh cinta untuk itu: D
user2161301
6

Penyebab paling jelas dari ini (termasuk untuk kelengkapan) adalah tidak tepat melemparkan pointer dan memanggil metode dari kelas yang salah.

NSArray* array = [[NSArray alloc] init];
[(NSDictionary*)array objectForKey: key]; // array is not a dictionary, hence exception
devios1
sumber
Ini adalah petunjuk yang bagus - tidak mensubklasifikasi tampilan atau objek data (mis. Dengan tidak menambahkan nama subklas) adalah cara lain hal ini terjadi
Brad M
4

Saya juga punya masalah yang sama.

Saya menghapus uibutton saya di storyboard saya dan membuatnya kembali .. sekarang semuanya berfungsi dengan baik.

Yohan Dahmani
sumber
3

Saya memiliki masalah yang sama, tetapi bagi saya solusinya sedikit berbeda. Dalam kasus saya, saya menggunakan Kategori untuk memperluas kelas yang ada (UIImage untuk beberapa kemampuan mengubah ukuran - lihat ini howto jika Anda tertarik) dan lupa menambahkan file * .m ke target build. Kesalahan bodoh, tetapi tidak selalu jelas ketika itu terjadi di mana mencarinya. Saya pikir ini layak untuk dibagikan ...

Mirko Jahn
sumber
3

Ini terjadi pada saya karena secara tidak sengaja menghapus "@IBAction func ..." di dalam kode kelas UIViewcontroller saya, jadi di Storyboard dibuat Outlet Referensi, tetapi pada saat runtime ada fungsi untuk memprosesnya.

Solusinya adalah menghapus referensi Outlet di dalam inspektur properti dan kemudian membuatnya kembali dengan menyeret kunci perintah ke kode kelas.

Semoga ini bisa membantu!

Guillermo
sumber
Demikian juga, ini juga terjadi pada saya ketika tombol referensi fungsi yang tidak ada lagi.
Josh Wolff
2

Saya pikir Anda harus menggunakan void, bukan IBAction pada tipe return. karena Anda mendefinisikan tombol secara terprogram.

Fa.Shapouri
sumber
2

Solusi lain yang mungkin: Tambahkan '-ObjC' ke argumen tautan Anda.

Penjelasan lengkap ada di sini: Kategori Objective-C di perpustakaan statis

Saya pikir intinya adalah: jika kategori didefinisikan di perpustakaan yang Anda tautkan secara statis, tautan tidak cukup pintar untuk menautkan dalam metode kategori. Bendera di atas membuat tautan tautan di semua kelas dan kategori objektif C, bukan hanya yang menurutnya perlu didasarkan pada analisis sumber Anda. (Jangan ragu untuk memperbaiki atau memperbaiki jawaban itu. Saya tahu bahasa yang ditautkan, jadi saya hanya nuri di sini).

Russ Egan
sumber
2

Saya memiliki kesalahan yang sama dan saya menemukan yang berikut:

Ketika Anda menggunakan kode

[self.refreshControl addTarget:self action:@selector(yourRefreshMethod:) forControlEvents:UIControlEventValueChanged];

Anda mungkin berpikir sedang mencari pemilih:

- (void)yourRefreshMethod{
    (your code here)
}

Tapi sebenarnya mencari pemilih:

- (void)yourRefreshMethod:(id)sender{
    (your code here)
}

Pemilih itu tidak ada, jadi Anda mendapatkan crash.

Anda dapat mengubah pemilih untuk menerima (id) pengirim untuk menyelesaikan kesalahan.

Tetapi bagaimana jika Anda memiliki fungsi lain yang memanggil fungsi refresh tanpa menyediakan pengirim? Anda memerlukan satu fungsi yang berfungsi untuk keduanya. Solusi mudah adalah dengan menambahkan fungsi lain:

- (void)yourRefreshMethodWithSender:(id)sender{
    [self yourRefreshMethod];
}

Dan kemudian ubah kode pulldown refresh untuk memanggil pemilih itu sebagai gantinya:

[self.refreshControl addTarget:self action:@selector(yourRefreshMethodWithSender:) forControlEvents:UIControlEventValueChanged];

Saya juga sedang melakukan kursus Stanford iOS pada Mac lama yang tidak dapat ditingkatkan ke versi terbaru Mac OSX. Jadi saya masih membangun untuk iOS 6.1, dan ini memecahkan masalah bagi saya.

Joseph Pride
sumber
2

Pada kasus saya, saya memecahkan masalah setelah 2 jam:

Pengirim (item tabBar) tidak memiliki Outlet Referensi . Jadi itu tidak menunjuk ke mana-mana.

Juste membuat outlet referensi yang sesuai dengan fungsi Anda.

Semoga ini bisa membantu kalian.

André DS
sumber
Hanya untuk menambahkan, dalam kasus saya, saya lupa untuk port IBActionke Swift. Jadi itu mengeluh bahwa ia ingin memanggil fungsi itu, tetapi tidak dapat ditemukan.
DevNebulae
1

Saat ini saya sedang belajar pengembangan iOS dan membaca buku "Beginning iOS6 Development" oleh aPress. Saya mendapatkan kesalahan yang sama di Bab 10: Storyboards.

Butuh waktu dua hari untuk mengetahuinya tetapi ternyata saya tidak sengaja mengatur tag sel TableView menjadi 1 padahal seharusnya tidak. Bagi siapa pun yang melakukan buku ini dan menerima kesalahan serupa, saya harap ini membantu.

Saya sangat berharap kesalahan di masa depan dalam kode saya lebih mudah ditemukan! ha ha ha. Kesalahan debug tidak melakukan apa pun untuk mendorong saya ke arah yang benar untuk mencari tahu (atau setidaknya saya terlalu baru untuk memahami debugger, lol).

Shannon Cole
sumber
1

Dalam kasus saya, saya menggunakan UIWebView dan saya melewatkan NSString pada parameter kedua, bukan NSURL. Jadi saya menduga bahwa tipe kelas yang salah diteruskan ke suatu fungsi dapat menyebabkan kesalahan ini.

jbaylina
sumber
1

..Dan Sekarang milikku

Saya memiliki tombol yang terhubung ke metode yang mengakses parameter tombol lain dan itu bekerja dengan baik, tetapi segera setelah saya mencoba melakukan sesuatu dengan tombol itu sendiri, saya mendapat crash. Saat mengkompilasi, tidak ada kesalahan yang ditampilkan .. Solusi?

Saya gagal menautkan tombol ke pemilik file. Jadi kalau ada orang di sini yang sebodoh saya, coba ini :)

pengguna2875404
sumber
1

Namun solusi / kasus lain yang sedikit berbeda.

Saya menggunakan Xamarin dan MvvmCross dan saya mencoba untuk mengikat UIButton ke ViewModel. Saya memiliki kabel UIButton ke Outlet dan TouchUpInside.

Saat Binding saya hanya menggunakan Outlet:

set.Bind (somethingOutlet).For ("TouchUpInside").To(vm => vm.Something);

Yang harus saya lakukan adalah menghapus koneksi aksi (TouchUpInside) di XCode dan itu menyelesaikannya.

PS Saya kira ini ada di pangkalannya semua yang terkait dengan jawaban sebelumnya dan untuk @Chris Kaminski pada khususnya, tapi saya harap ini membantu seseorang ...

Bersulang.

YKa
sumber
1

Saya memiliki masalah yang sama. Masalahnya bagi saya adalah bahwa satu tombol memiliki dua metode Aksi. Apa yang saya lakukan adalah membuat metode tindakan pertama untuk tombol saya dan kemudian menghapusnya di view controller, tetapi lupa untuk memutuskan koneksi di storyboard utama di inspektur koneksi. Jadi ketika saya menambahkan metode tindakan kedua, sekarang ada dua metode tindakan untuk satu tombol, yang menyebabkan kesalahan.

Harshil.Chokshi
sumber
1

Bagi saya, itu adalah koneksi sisa yang dibuat di interfacebuilder dan ctrl-dragging. Nama koneksi yang terputus ada di log kesalahan

*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[NameOfYourApp.NameOfYourClass nameOfCorruptConnection:]:
unrecognized selector sent to instance 0x7f97a48bb000'

Saya memiliki tindakan yang ditautkan ke tombol. Menekan tombol membuat aplikasi mogok karena Outlet tidak lagi ada dalam kode saya. Mencari nama di log menuntun saya ke sana di storyboard. Dihapus, dan kecelakaan itu hilang!

Tom Brinkkemper
sumber
0

Saya membalas ke Leonard Challis, karena saya juga mengambil kelas Stanford iOS C193P, seperti juga pengguna "oli206"

"Mengakhiri aplikasi karena pengecualian 'NSInvalidArgumentException' tanpa alasan, alasan:"

Masalahnya adalah saya memiliki tombol "Enter" pada kalkulator yang terhubung dua kali, dan seorang teman menunjukkan bahwa melakukan pemeriksaan tombol di Storyboard menunjukkan bahwa 2 entri berada pada atribut "Touch Up Inside" ketika saya mengklik kanan pada tombol "Enter". Menghapus salah satu dari dua "Sentuh Di Dalam" "Acara Terkirim" memecahkan masalah.

Ini menunjukkan bahwa masalahnya dipicu (untuk kelas video C193P di Walkthrough Calculator on Assignment 1) sebagai 2 peristiwa yang dikirim, salah satunya menyebabkan pengecualian.

Peter_from_NYC
sumber
Saya punya 3 entri bagaimana. :)
1.21 gigawatts
0

Itu bisa terjadi ketika Anda tidak menetapkan ViewController ke ViewControllerScene di InterfaceBuilder. Jadi ViewController.m tidak terhubung ke adegan apa pun.

Vincent
sumber
0

Termasuk bagian saya. Saya terjebak pada ini untuk sementara waktu, sampai saya menyadari saya telah membuat proyek dengan ARC (penghitungan penghitungan otomatis) dinonaktifkan. Set cepat ke YA pada opsi itu menyelesaikan masalah saya.

caiocpricci2
sumber
0

Penyebab lain yang benar-benar konyol dari ini adalah memiliki pemilih yang didefinisikan di antarmuka (.h) tetapi tidak dalam implementasi (.m) (pe typo)

jla
sumber
0

Alasan / solusi lain untuk ditambahkan ke daftar. Yang ini disebabkan oleh iOS6.0 (dan / atau pemrograman buruk). Dalam versi yang lebih lama, pemilih akan cocok jika jenis parameter cocok, tetapi di iOS 6.0 saya mengalami crash pada kode yang sebelumnya berfungsi di mana nama parameter tidak benar.

Saya sedang melakukan sesuatu seperti

[objectName methodName:@"somestring" lat:latValue lng:lngValue];

tetapi dalam definisi (keduanya. h dan. m) saya miliki

(viod) methodName:(NSString *) latitude:(double)latitude longitude:(double)longitude;

Ini bekerja dengan baik di iOS5 tetapi tidak pada 6, bahkan bangunan yang sama persis dikerahkan ke perangkat yang berbeda.

Saya tidak mengerti mengapa kompiler tidak dapat memberi tahu saya hal ini - masalah diselesaikan.

Tim T
sumber
0

Ini juga mungkin terjadi ketika Anda ingin mengatur properti dari ControllerA ke properti publik di dalam kelas ControllerB kustom dan Anda belum menetapkan "Kelas Kustom" di dalam inspektur identitas di storyboard.

Francisco Gutiérrez
sumber
0

Masalah dan solusi saya berbeda dan saya pikir saya harus mempostingnya di sini sehingga pembaca yang akan datang dapat menyelamatkan kepala mereka dari terbentur ke dinding.

Saya mengalokasikan xib yang berbeda untuk UIVIewController yang sama dan bahkan setelah mencari kemana-mana saya tidak dapat menemukan cara untuk memperbaikinya. Kemudian saya memeriksa AppDelegate saya di mana saya menelepon initWithNibNamedan dapat melihat bahwa saat menyalin kode, saya mengubah nama xib, tetapi lupa mengubah UIViewControllerkelas. Jadi, jika tidak ada solusi yang cocok untuk Anda, periksa initWithNibNamemetode Anda .

cupu
sumber
0

Terjadi pada saya karena argumen kendala yang saling bertentangan.

Alex Bedro
sumber