Ошибка "нераспознанный селектор отправлен в экземпляр" в Objective-C

Я создал кнопку и добавил действие для нее, но как только она была вызвана, я получил эту ошибку:

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

41 ответ

Решение

Похоже, вы не управляете контроллером представления памяти должным образом, и в какой-то момент его освобождают, что вызывает numberButtonClicked: метод для отправки другому объекту, который сейчас занимает память, которую ранее занимал контроллер представления...

Убедитесь, что вы правильно удерживаете / отпускаете свой контроллер вида.

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

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

Был изменен на:

- (IBAction)buttonPressed {

Щелчок правой кнопкой мыши по рассматриваемой кнопке UIB показал, что событие Touch Up Inside было связано с контроллером представления buttonPressed: метод. Удаление этого и переназначение его модифицированному методу сработало.

Это был лучший ответ Google для этой проблемы, но у меня была другая причина / результат - я решил добавить свои два цента на случай, если другие столкнутся с этой проблемой.

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

Поэтому убедитесь, что ваши действия правильно настроены.

Хорошо, я должен скинуться здесь. ОП динамически создал кнопку. У меня была похожая проблема, и ответ (после нескольких часов охоты) настолько прост, что меня тошнило.

Когда используешь:

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

Как обычно, это всегда очевидный ответ, который пропускается.

В моем случае функция не ожидала аргумента, но кнопка была настроена для отправки аргумента, вызвавшего ошибку. Чтобы это исправить, мне пришлось перепрограммировать обработчик событий.

Вот моя функция:

Обратите внимание, что он не содержит аргументов.

Вот изображение моей конфигурации кнопок (щелкните ее правой кнопкой мыши, чтобы просмотреть):

Обратите внимание, что есть 3 обработчика событий.

Чтобы это исправить, мне пришлось удалить каждый из элементов события, поскольку один из них отправлял ссылку на себя в функцию enterPressed. Чтобы удалить эти элементы, я нажимал на маленький значок "x" рядом с названием каждого элемента, пока элементы не отображались.

Далее мне пришлось заново подключить кнопку к событию. Для этого удерживайте нажатой клавишу "Control", а затем перетащите линию от кнопки к действию. Стоит сказать "Подключи действие". Примечание: мне пришлось перезапустить XCode, чтобы это работало по какой-то причине; в противном случае это только позволяет мне вставлять действия (или создать новое действие) выше или ниже функции.

Теперь у вас должен быть один обработчик события, связанный с событием кнопки без аргументов:

Этот ответ дополняет ответ @Leonard Challis, который вы также должны прочитать.

Это также может произойти, если вы не установили "Класс" представления в конструкторе интерфейса.

В моем случае я использовал NSNotificationCenter и пытался использовать селектор, который не принимал аргументов, но добавлял двоеточие. Удаление двоеточия решило проблему.

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

Смотрите ответ Адама Розенфилда здесь: Селекторы в Цели C

У меня была эта проблема с проектом 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

Наиболее очевидной причиной этого (включенной для полноты) является неправильное приведение указателя и вызов метода неправильного класса.

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

Как отладить «неопознанный селектор, отправленный в экземпляр»

В большинстве случаев Xcode не приводит нас к точной строке, где возникает эта проблема. При сбое приложения вы не увидите строку кода, вызвавшую это, вместо этого вы будете перенаправлены в класс делегата приложения с ошибкой, выдающей что-то следующее:

      [UITableViewCellContentView image]: unrecognized selector sent to instance

или же

      [__NSDictionaryI objectAtIndex:] unrecognized selector sent to instance

или же

      *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[TestApp.MyViewController viewDidLoad:]: unrecognized selector sent to instance 0xDABCDD'

Как найти строку кода, вызывающую это:

Перейти к навигатору точек останова. Нажмите «+». нажмите «Точка останова исключения». Появится новый виджет, подобный следующему.

Добавьте следующий блок условий:

      -[NSObject(NSObject) doesNotRecognizeSelector:]

Вы также можете поставить точку останова для всех исключений. Теперь снова запустите свой код. на этот раз точка останова сработает при возникновении этого исключения.

НАПИСАНО: Прафулла Сингх

Полное объяснение: https://prafullkumar77.medium.com/how-to-debug-unrecognized-selector-send-to-instance-402473bc23d

У меня тоже была такая же проблема.

Я удалил свой uibutton в моей раскадровке и воссоздал его.. теперь все работает отлично.

У меня была та же ошибка, и я обнаружил следующее:

Когда вы используете код

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

Вы можете подумать, что он ищет селектор:

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

Но это на самом деле ищет селектор:

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

Этот селектор не существует, поэтому вы получите сбой.

Вы можете изменить селектор для получения (id) отправителя, чтобы устранить ошибку.

Но что, если у вас есть другие функции, которые вызывают функцию обновления без предоставления отправителя? Вам нужна одна функция, которая работает для обоих. Простое решение - добавить еще одну функцию:

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

А затем измените код обновления выпадающего меню, чтобы вместо этого вызывать этот селектор:

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

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

Другое возможное решение: добавьте '-ObjC' к своим аргументам компоновщика.

Полное объяснение здесь: категории Objective-C в статической библиотеке

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

У меня была похожая проблема, но для меня решение было немного другим. В моем случае я использовал Category для расширения существующего класса (UIImage для некоторых возможностей изменения размера - см. Это руководство на случай, если вам интересно) и забыл добавить файл *.m в цель сборки. Глупая ошибка, но не всегда очевидная, когда случается, где искать. Я думал, что стоит поделиться...

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

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

Надеюсь, поможет!

Я думаю, что вы должны использовать void вместо IBAction в типе возврата. потому что вы определили кнопку программно.

В моем случае я решил проблему через 2 часа:

У отправителя (элемента tabBar) не было ни одного источника ссылок. Так что это никуда не указывало.

Juste создайте ссылочный выход, соответствующий вашей функции.

Надеюсь, это поможет вам, ребята.

Еще одно немного другое решение / случай.

Я использую Xamarin и MvvmCross, и я пытался привязать UIButton к ViewModel. Я подключил UIB-кнопку к розетке и TouchUpInside.

При связывании я использую только розетку:

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

Все, что мне нужно было сделать, это удалить соединение action (TouchUpInside) в XCode, и это решило его.

PS Я полагаю, что все это основано на предыдущих ответах и, в частности, на @Chris Kaminski, но я надеюсь, что это кому-то поможет...

Приветствия.

..А теперь моя

У меня была кнопка, связанная с методом, который обращался к параметру другой кнопки, и это работало отлично, НО, как только я попытался что-то сделать с самой кнопкой, у меня произошел сбой. Во время компиляции ошибки не отображались. Решение?

Мне не удалось связать кнопку с владельцем файла. Так что, если кто-нибудь здесь так же глуп, как я, попробуйте это:)

В настоящее время я изучаю разработку под iOS и прохожу книгу "Начало разработки под iOS6" от aPress. Я получил ту же ошибку в главе 10: раскадровки.

Мне потребовалось два дня, чтобы понять это, но обнаружил, что я случайно установил тег ячейки TableView в 1, когда мне не следовало этого делать. Для всех, кто делает эту книгу и получает подобную ошибку, я надеюсь, что это поможет.

Я действительно надеюсь, что будущие ошибки в моем коде будет легче найти! хахаха. Ошибка отладки никак не подтолкнула меня в правильном направлении, чтобы понять это (или, по крайней мере, я слишком новичок, чтобы понимать отладчик, смеется).

В моем случае я использовал UIWebView и передал NSString во втором параметре вместо NSURL. Поэтому я подозреваю, что неправильные типы классов, переданные в функции, могут вызвать эту ошибку.

Для меня это было оставшееся соединение, созданное в interfacebuilder bij ctrl-dragging. Имя разорванного соединения было в журнале ошибок

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

У меня было действие, связанное с кнопкой. Нажатие кнопки привело к сбою приложения, потому что в моем коде больше не было Outlet. Поиск имени в журнале привел меня к нему в раскадровке. Удалил его, и авария исчезла!

Я была такая же проблема. Проблема для меня заключалась в том, что у одной кнопки было два метода действий. Я создал первый метод действия для моей кнопки, а затем удалил его в контроллере представления, но забыл отключить соединение в основной раскадровке в инспекторе соединений. Поэтому, когда я добавил второй метод действия, теперь для одной кнопки было два метода действия, что вызвало ошибку.

Произошло со мной из-за противоречивых аргументов ограничения.

Я получил эту проблему, пытаясь старый код формата в Swift3,

let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(self.respond))

изменяя action:"respond:" к действию: #selector(self.respond) исправил проблему для меня.

В моем случае в iOS 13 мне нужно было только реализовать всю функцию и части вызова селектора, помещенные в основной поток.

Это также может произойти, если вы хотите установить свойство из ControllerA в открытое свойство внутри пользовательского класса ControllerB, и вы еще не установили "Пользовательский класс" внутри инспектора идентификации в раскадровках.

Еще одна причина / решение добавить в список. Это вызвано 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, даже на одной и той же сборке, развернутой на разных устройствах.

Во всяком случае, я не понимаю, почему компилятор не сказал мне этого - проблема единственная.

ОК СПИСОК! Я ОЧЕНЬ новичок в XCODE, у меня была эта проблема, и я понял ее! Итак, если это похоже на вас, вот ответ:

Когда вы управляете + щелкаете и перетаскиваете кнопку в файл ViewController (чтобы вы могли его закодировать), вам будет предложено заполнить свойства кнопки во всплывающем окне.

Внизу всплывающего окна (под Типом) будет написано "ОТПРАВИТЕЛЬ".

НЕОБХОДИМО ИЗМЕНИТЬ ЕГО НА "НЕТ"

Включая мою долю. Я застрял на этом некоторое время, пока не понял, что создал проект с отключенным ARC(ссылка на автоматический подсчет). Быстрый выбор ДА для этой опции решил мою проблему.

Другие вопросы по тегам