Помилка "нерозпізнаний селектор, надісланий екземпляру" в "Objective-C"


155

Я створив кнопку і додав до неї дію, але як тільки вона викликала, я отримав цю помилку:

-[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'

Це мій код:

- (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(@"---");
}

Відповіді:


187

Схоже, ви не пам’ятаєте належним чином керування контролером перегляду, і він переноситься в якийсь момент - це призводить до того, що numberButtonClicked:метод буде пересланий на інший об’єкт, який зараз займає пам’ять, яку раніше займав контролер перегляду ...

Переконайтеся, що ви належним чином утримуєте / звільняєте контролер перегляду.


105
Це дуже проникливий діагноз із дуже небагато рядків коду.
Майкл Моррісон

41
ОК, тому проблема виявлена ​​... але "Переконайтесь, що ви належним чином утримуєте / звільняєте контролер перегляду". - це пропозиція, а не рішення.
Алекс Грей

12
@ алекс сірий, що? Правильне управління пам'яттю на контролері перегляду вирішило проблему ... Я не розумію, як це не є рішенням?
Ясарієн

28
правильно. хоча це, здається, "виправлення" .. і я можу бути в меншості, (хоча мені все ще вдається існувати), але зв'язок між проблемою та рішенням не відразу очевидний. наприклад, я зіткнувся, -[NSWindow end]: unrecognized selector sent to instance 0x100523e80 і хоча я усвідомлюю схожість з ОП, і навіть можливо причиною проблеми з вашої відповіді, реалізація виправлення не відразу очевидна
Алекс Грей

12
Це відразу очевидно. Ваше управління пам’яттю NSWindow невірно десь уздовж лінії. Пройдіть його життєвий цикл і виправте це.
Ясарієн

127

Для тих, хто потрапляє сюди через Google, як я, який, ймовірно, стосується більше Xcode 4.2 + / iOS 5+, що з ARC. У мене була така ж помилка " нерозпізнаний селектор, надісланий до примірника ". У моєму випадку у мене було встановлено цільову дію UIButton, щоб передати себе як параметр відправника, але пізніше зрозумів, що мені це не потрібно, і видалив це з коду. Отже, щось на кшталт:

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

Було змінено на:

- (IBAction)buttonPressed {

Клацання правою кнопкою миші на відповідній кнопці UIB показало, що подія Touch Up Inside пов'язана з методом кнопки контролерів переглядуПрес:: Видалення цього та переназначення його до модифікованого методу спрацювало частування.


Це було дуже корисно, хоча я думаю, що його власне запитання та відповідь полегшить пошук.
Кертіс Індервіше

@LeonardChallis Як ви можете посилатися на відправника у buttonPress, якщо він не переданий як параметр?
zakdances

8
Дуже корисна відповідь. Я просто зіткнувся з цією точною проблемою, і ваше рішення було абсолютно правильним. Коли це сталося, слідкував за класом iOS Stanford iOS на iTunesU. Ще раз дякую за вашу відповідь!
Маршалл Альсуп

1
@LeonardChallis Дякую Я додав безкоштовну відповідь до вашої відповіді.
1,21 гігаватта

1
Я просто боровся з подібною проблемою, видалив параметр відправника з функції вибору, а потім задумався, як отримати відправника. У моєму випадку я отримував помилку, оскільки забув поставити двокрапку після зворотного виклику селектора, тим самим викликаючи невідповідність послідовності виклику. За допомогою двокрапки я можу тримати аргумент відправника.

74

Це була головна відповідь Google на це питання, але у мене була інша причина / результат - я думав, що додаю два центи, якщо інші натрапляють на цю проблему.

У мене було подібне питання саме цього ранку. Я виявив, що якщо ви клацніть правою кнопкою миші елемент інтерфейсу, який видає вам проблему, ви зможете побачити, які з'єднання створено. У моєму випадку у мене була кнопка, підключена до двох дій. Я видалив дії з меню правої кнопки миші та перемотав їх, і моя проблема була виправлена.

Тож переконайтеся, що дії ви з'єднані правильно.


Це була моя проблема. Я перейменував функцію і змінив код, але не змінив з'єднання у файлі xib.
BFTrick

2
СПАСИБІ! Виявилося, що у мене було три методи, на які я видалив ще посилання. Мене турбує тиждень!
erdekhayser

25

Гаразд, я маю чіпнути тут. ОП динамічно створила кнопку . У мене було подібне питання, і відповідь (після години полювання) настільки проста, що мені стало нудно.

При використанні:

action:@selector(xxxButtonClick:)

or (as in my case)

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

Якщо ви помістите двокрапку в кінці рядка - вона передасть відправника. Якщо ви не помістите двокрапку в кінці рядка, вона не стане, і приймач отримає помилку, якщо очікує її. Пропустити двокрапку легко, якщо ви динамічно створюєте назву події.

Параметри коду приймача виглядають приблизно так:

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

Як завжди, це завжди очевидна відповідь, яку можна пропустити.


1
Дуже дякую! Це була моя проблема (не ставити двокрапку ":" в кінці імені селектора). Чому, майже завжди, найглупіші прості речі, змушують нас вундерки бити головою об стіну о 3 ранку? Дійсно ДЯКУЮ!
TWright

23

У моєму випадку функція не очікувала аргументу, але кнопка була налаштована для надсилання одного, що викликав помилку. Щоб виправити це, мені довелося переключити обробник подій.

Ось моя функція:

введіть тут опис зображення

Зауважте, він не містить аргументів.

Ось зображення конфігурації моєї кнопки (клацніть правою кнопкою миші кнопку, щоб переглянути її):

введіть тут опис зображення

Зауважте, є 3 обробники подій.

Щоб виправити це, мені довелося видалити кожен елемент події, оскільки один з них надсилав посилання на функцію enterPress. Щоб видалити ці елементи, я натискав на значок маленького х поруч із назвою кожного елемента, поки не було показано жодних елементів.

введіть тут опис зображення

Далі мені довелося знову підключити кнопку до події. Для цього утримуйте клавішу Control, а потім перетягніть рядок від кнопки до дії. Слід сказати «Підключіть дії». Примітка: мені довелося перезапустити XCode, щоб це чомусь працювало; інакше це дозволить мені лише вставити дії (ака створити нову дію) над або під функцією.

введіть тут опис зображення

Тепер у вас повинен бути один обробник подій, підключений до події кнопки, яка не передає аргументів:

введіть тут опис зображення

Ця відповідь доповнює відповідь @Leonard Challis, яку ви також повинні прочитати.


14

Це також може статися, якщо ви не встановите "Клас" подання в програмі інтерфейсів.


Ах, дякую! Це спричинило збій мого додатка на segue, просто забув встановити клас контролера.
Eichhörnchen

Чому потрібно знати клас? Я намагаюся використовувати UITableViewSection як UIView, і тому я отримую цю помилку. Компілятор каже, що UITableViewSection не існує, тому я припускаю його внутрішній UIKit.
Ян Варбуртон

13

У моєму випадку я використовував NSNotificationCenter і намагався використовувати селектор, який не брав аргументів, але додав двокрапку. Видалення товстої кишки вирішило проблему.

Якщо ви використовуєте ім'я селектора, не використовуйте зворотну двокрапку, якщо немає аргументів. Якщо є один аргумент, використовуйте одну зворотну кишку. Якщо аргументів є більше, ви повинні назвати їх разом із кінцевою двокрапкою для кожного аргументу.

Дивіться відповідь Адама Розенфілда тут: Селектори в Objective-C?


11

У мене була ця проблема з проектом Swift, де я створюю кнопки динамічно. Код проблеми:

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).")
}

Рішенням було додати повну двокрапку ':' після дії: напр

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).")
    }

Повний приклад тут: https://developer.apple.com/library/content/samplecode/UICatalog/Listings/Swift_UIKitCatalog_DefaultToolbarViewController_swift.html


Щойно слідуючи за підручником і прочитавши підказку про цю саме цю проблему - я потрапив на це: D
user2161301

6

Найбільш очевидною причиною цього (включається для повноти) є неправильне введення покажчика та виклик методу неправильного класу.

NSArray* array = [[NSArray alloc] init];
[(NSDictionary*)array objectForKey: key]; // array is not a dictionary, hence exception

Це хороша підказка - не підкласифікація представлення даних або об’єкта даних (наприклад, невдача імені підкласу) - це ще один спосіб
Бред М

4

У мене теж було таке ж питання.

Я видалив uibutton в моїй розгортці і відтворив його .. тепер усе працює добре.


3

У мене була схожа проблема, але для мене рішення було дещо іншим. У моєму випадку, я використовував категорію , щоб розширити існуючий клас (UIImage для деяких зміни обсягу повноважень - побачити цей HOWTO в разі , якщо ви зацікавлені) і забув додати * .m файл в цільову збірці. Дурна помилка, але не завжди очевидна, коли трапляється, де її шукати. Я думав, що варто поділитися ...


3

Це сталося з моїм тим, що випадково стерти "@IBAction func ..." всередині мого коду класу UIViewcontroller, тому в аркуші розробки було створено Reference Outlet, але під час виконання функцій для його обробки була будь-яка функція.

Рішенням було видалити посилання Outlet всередині інспектора властивостей, а потім відтворити його перетягуванням за допомогою командного ключа до коду класу.

Сподіваюся, це допомагає!


Так само це трапилося і зі мною, коли кнопка посилалася на функцію, яка більше не існувала.
Джош Волф

2

Я думаю, вам слід використовувати пустоту замість IBAction у зворотному виді. тому що ви визначили кнопку програмно.


2

Інше можливе рішення: Додайте до аргументів лінкера '-ObjC'.

Повне пояснення тут: Категорії Objective-C у статичній бібліотеці

Я думаю, що суть полягає в тому, що якщо категорія визначена в бібліотеці, з якою ви статечно пов'язуєте, то лінкер недостатньо розумний для того, щоб зв’язувати методи категорії. Наведений вище прапор робить посилання на лінкер у всіх об'єктивних класах і категоріях C, а не лише в тих, які, на його думку, потребує на основі аналізу вашого джерела. (Будь ласка, не соромтесь налаштувати або виправити цю відповідь. Я знав пов'язані мови, тому я просто папугую тут).


2

У мене була така ж помилка, і я виявив таке:

Коли ви використовуєте код

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

Ви можете подумати, що він шукає селектора:

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

Але він насправді шукає селектора:

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

Такого селектора не існує, тож ви отримаєте збій.

Ви можете змінити селектор для отримання (ідентифікатора) відправника, щоб вирішити помилку.

Але що робити, якщо у вас є інші функції, які викликають функцію оновлення, не надаючи відправника? Вам потрібна одна функція, яка працює для обох. Просте рішення - додати ще одну функцію:

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

А потім змініть код оновлення для виклику, щоб зателефонувати цьому селектору:

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

Я також роблю курс Stanford iOS на старшому Mac, який неможливо оновити до новітньої версії Mac OSX. Тому я все ще будую для iOS 6.1, і це вирішило проблему для мене.


2

У моєму випадку я вирішив проблему через 2 години:

У відправника (елемента tabBar) не було жодної розсилки для посилань . Так воно не вказувало нікуди.

Juste створити референтну розетку відповідно до вашої функції.

Сподіваюся, це може допомогти вам, хлопці.


Просто додам, у моєму випадку я забув перенести порт IBActionна Swift. Тож він скаржився, що хоче викликати цю функцію, але її не вдалося знайти.
DevNebulae

1

В даний час я вивчаю розробку iOS і проходжу книгу "Початок iOS6 розробки" від aPress. Я отримував таку ж помилку в главі 10: Розповіді.

На це знадобилося два дні, але я дізнався, що випадково я встановив тег комірки TableView на 1, коли мені не довелося. Для всіх, хто робить цю книгу і отримує подібну помилку, сподіваюся, це допомагає.

Я дуже сподіваюся, що майбутні помилки в моєму коді простіше знайти! хахаха. Помилка налагодження нічого не підштовхувала мене в правильному напрямку, щоб зрозуміти це (або, принаймні, я занадто новий, щоб зрозуміти налагоджувач, хай).


1

У моєму випадку я використовував UIWebView, і я передав NSString у другому параметрі замість NSURL. Тому я підозрюю, що неправильні типи класів, передані функції, можуть спричинити цю помилку.


1

..А тепер моя

У мене була кнопка, пов’язана з методом, який отримував доступ до параметра іншої кнопки, і він працював чудово, АЛЕ як тільки я спробував щось зробити із самою кнопкою, стався збій. Під час компіляції помилка не відображалася. Рішення?

Не вдалося зв’язати кнопку з власником файлу. Тож якщо хтось тут такий дурний, як я, спробуйте це :)


1

Ще одне трохи інше рішення / випадок.

Я використовую Xamarin і MvvmCross, і я намагався прив’язати UIButton до ViewModel. У мене було підключено UIButton до розетки та TouchUpInside.

Під час прив'язки я використовую лише розетку:

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

Все, що мені потрібно було зробити, - це видалити підключення дії (TouchUpInside) у XCode, і це вирішило.

PS Я думаю, що це в його основі все, що стосується попередніх відповідей і зокрема до @Chris Kaminski, але я сподіваюся, що це комусь допоможе ...

Ура.


1

У мене було те саме питання. Проблемою для мене було те, що одна кнопка мала два способи дій. Що я зробив, це створити метод першої дії для моєї кнопки, а потім видалив її в контролері перегляду, але забув відключити з'єднання на головній таблиці розвідки в інспекторі з'єднань. Тож коли я додав другий метод дії, тепер було два способи дії для однієї кнопки, що спричинило помилку.


1

Для мене це було залишкове з'єднання, створене в інтерфейсі bii ctrl-drag drag. Ім'я розірваного з'єднання було в журналі помилок

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

У мене була дія, пов’язана з кнопкою. Натискання кнопки перервало додаток, оскільки в моєму коді більше не існувало Outlet. Пошук імені в журналі привів мене до цього в раскадровці. Видалено його, і аварії вже не було!


0

Я відповідаю Леонарду Чаллісу, оскільки я також брав клас Stanion iOS C193P, як і користувач "oli206"

"Закінчення програми через невиконане виключення" NSInvalidArgumentException ", причина:"

Проблема полягала в тому, що у мене двічі була підключена кнопка "Ввести" на калькуляторі, і друг зазначив, що, перевіривши кнопку на Дошці розгортки, показало, що 2 атрибути були на атрибутах "Touch Up Inside", коли я клацнув правою кнопкою миші на кнопка "Enter". Видалення однієї з двох "Touch Up Inside" "Надісланих подій" вирішило проблему.

Це показало, що проблема спрацьовує (для відеокласу C193P в Проході калькулятора за призначенням 1) як 2 надіслані події, один з яких спричинив виняток.


У мене було 3 записи, як. :)
1,21 гігаватта

0

Це може статися, коли ви не призначите ViewController ViewControllerScene в InterfaceBuilder. Тож ViewController.m не підключений до жодної сцени.



0

Ще одна справді нерозумна причина цього - це те, що селектор визначено в інтерфейсі (.h), але не в реалізації (.m) (pe typo)


0

Ще одна причина / рішення додати до списку. Це спричинено iOS6.0 (та / або поганим програмуванням). У старих версіях селектор відповідатиме, якщо типи параметрів збігаються, але в iOS 6.0 я отримав збої в раніше працюючому коді, де ім'я параметра не було правильним.

Я робив щось подібне

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

але у визначенні (і .h і .m) я мав

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

Це працювало чудово на iOS5, але не на 6, навіть та сама збірка, розгорнута на різних пристроях.

Я не розумію, чому компілятор coud не сказав мені це, у всякому разі - проблема вирішена.


0

Це також може статися, коли ви хочете встановити властивість з ControllerA на публічну власність у користувацькому класі ControllerB, а ви ще не встановили "Спеціальний клас" всередині інспектора ідентичності в дошках розповідей.


0

Моя проблема та рішення були різними, і я подумав, що я повинен її розмістити тут, щоб майбутні читачі могли врятувати голову від удару в стіну.

Я виділяв різні xib тому самому UIVIewController і навіть після пошуку скрізь я не міг знайти, як це виправити. Потім я перевірив свій AppDelegate, куди дзвонив, initWithNibNameі бачу, що під час копіювання коду я змінив ім'я xib, але забув змінити UIViewControllerклас. Тож якщо жодне рішення не працює для вас, перевірте свій initWithNibNameметод.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.