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

Answers:


187

看来您没有正确地管理视图控制器的内存,并且在某个时候将其释放—这导致该numberButtonClicked:方法被发送到另一个对象,该对象现在正在占用视图控制器以前占用的内存...

确保正确保留/释放视图控制器。


105
从几行代码来看,这是非常精明的诊断。
迈克尔·莫里森

41
好的,这样就可以确定问题了……但是“请确保您正确保留/释放了视图控制器。” 是一个建议,而不是解决方案。
亚历克斯·格雷

12
@alex grey,什么?在视图控制器上进行适当的内存管理解决了该问题……我不知道这不是解决方案吗?
Jasarien'9

28
正确。尽管这似乎确实是“解决办法”,而且我可能只占少数,(尽管我仍然设法存在),但是问题和解决方案之间的联系并不立即明显。例如,我遇到了一个问题-[NSWindow end]: unrecognized selector sent to instance 0x100523e80 ,尽管我意识到与OP的相似之处,甚至可能是您回答中引起问题的原因,但修复的实施并非立即显而易见
Alex Gray

12
这是显而易见的。您的NSWindow内存管理不正确。经历它的生命周期并进行更正。
2011年

127

对于像我一样通过Google到达这里的人们,这可能与Xcode 4.2 + / iOS 5+的关系更大,而ARC则更是如此。我遇到了相同的错误“ 无法识别的选择器发送到实例 ”。在我的情况下,我将UIButton的目标动作设置为将自身作为sender参数传递,但后来意识到我不需要它并在代码中将其删除。因此,类似:

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

更改为:

- (IBAction)buttonPressed {

右键单击有问题的UIButton,表明Touch Up Inside事件与视图控制器的buttonPressed:方法相关联。删除它,然后将其重新分配给修改后的方法,可以解决问题。


这很有帮助,尽管我认为它自己的问题和响应将使查找起来更容易。
Curtis Inderwiesche 2012年

@LeonardChallis如果未将其作为参数传递,如何在buttonPressed中引用发件人?
zakdances 2012年

8
非常有帮助的回应。我只是遇到了这个确切的问题,您的解决方案是正确的。发生这种情况时,我正在iTunesU上学习Stanford iOS课程。再次感谢您的回答!
Marshall Alsup

1
@LeonardChallis谢谢。我为您的答案添加了免费答案。
2013年

1
我只是在努力解决类似的问题,从选择器函数中删除了sender参数,然后想知道如何获取sender。就我而言,出现错误是因为我忘记在选择器回调后面放一个冒号,从而导致调用序列不匹配。使用冒号,我可以保留sender参数。

74

这是Google针对此问题的最佳答案,但是我有不同的原因/结果-我想我会加2美分,以防其他人偶然发现此问题。

我今天早上有一个类似的问题。我发现,如果右键单击出现问题的UI项,则可以看到已创建的连接。就我而言,我的按钮最多可连接两个动作。我从右键菜单中删除了这些操作,然后重新连接了它们,问题得到解决。

因此,请确保您的操作正确连接。


这是我的问题。我重命名了一个函数并更改了我的代码,但没有更改xib文件中的连接。
BFTrick 2012年

2
谢谢!原来,我有三种删除的方法仍在引用。困扰我一个星期!
erdekhayser 2013年

25

好的,我必须在这里插卡。OP 动态创建按钮。我有一个类似的问题,答案(经过几个小时的狩猎)是如此简单,以至于让我恶心。

使用时:

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 2013年

23

在我的情况下,该函数不需要参数,但是按钮配置为发送一个导致错误的参数。为了解决这个问题,我不得不重新连接事件处理程序。

这是我的功能:

在此处输入图片说明

注意它不包含任何参数。

这是我的按钮配置的图像(右键单击按钮以查看它):

在此处输入图片说明

注意有3个事件处理程序。

为了解决这个问题,我必须删除每个事件项,因为其中一个是将对自身的引用发送给enterPressed函数。要删除这些项目,我单击了每个项目名称旁边的小x图标,直到没有显示任何项目。

在此处输入图片说明

接下来,我必须将按钮重新连接到事件。为此,请按住Control键,然后将一条线从按钮拖到操作上。它应该说“连接动作”。注意:出于某种原因,我必须重新启动XCode才能起作用。否则,它只能让我在函数上方或下方插入动作(也称为创建新动作)。

在此处输入图片说明

现在,您应该将单个事件处理程序连接到不传递任何参数的button事件:

在此处输入图片说明

这个答案补充了@Leonard Challis的答案,您也应该阅读。


14

如果您没有在界面构建器中设置视图的“类”,也会发生这种情况。


谢谢你!这导致我的应用程序因故障而崩溃,只是忘记了设置控制器的类。
Eichhörnchen

为什么需要了解班级?我正在尝试将UITableViewSection用作UIView,因此出现此错误。编译器说UITableViewSection不存在,所以我认为它在UIKit内部。
伊恩·沃伯顿

13

就我而言,我使用的是NSNotificationCenter,并尝试使用不带参数但选择冒号的选择器。除去冒号可解决此问题。

使用选择器名称时,如果没有参数,请不要使用结尾的冒号。如果有一个参数,请使用一个尾部冒号。如果有多个参数,则必须为每个参数命名它们,并在结尾加上冒号。

在这里查看Adam Rosenfield的答案: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


在遵循了教程并阅读了有关此完全相同问题的提示后,我就为它所

6

最明显的原因(包括完整性在内)是不正确地转换了指针并调用了错误类的方法。

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

这是一个很好的提示-不对视图或数据对象进行子类化(例如,由于未添加子类名称)是发生这种情况的另一种方式
Brad M


3

我有一个类似的问题,但是对我来说解决方案略有不同。就我而言,我用了一个类别,以扩展现有类(UIImage的一些调整能力-看到这个HOWTO如果你有兴趣),忘了将* .m文件添加到构建目标。愚蠢的错误,但发生在哪里时并不总是显而易见。我认为值得分享...


3

这是我的事,因为不小心擦除了UIViewcontroller类代码中的“ @IBAction func ...”,因此在Storyboard中创建了Reference Outlet,但在运行时有任何函数可以对其进行处理。

解决方案是删除属性检查器中的“出口”引用,然后使用命令键将其拖动到类代码上以重新创建它。

希望能帮助到你!


同样,当按钮引用的功能不再存在时,这也发生在我身上。
乔什·沃尔夫

2

我认为您应该在返回类型中使用void而不是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)
}

该选择器不存在,因此会导致崩溃。

您可以将选择器更改为接收(id)发送方,以解决错误。

但是,如果您有其他功能在提供发送方的情况下调用刷新功能该怎么办?您需要一个对两者都适用的功能。简便的解决方案是添加另一个功能:

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

然后修改刷新下拉代码以改为调用该选择器:

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

我还在旧版Mac上进行斯坦福iOS课程,但无法升级到最新版本的Mac OSX。因此,我仍在为iOS 6.1进行构建,这为我解决了问题。


2

就我而言,两小时后我解决了问题:

发件人(一个tabBar项目)没有任何参考插座。所以它没有指向。

Juste 创建与您的功能相对应的引用出口

希望这可以帮助你们。


补充一点,在我的情况下,我忘了IBAction将Swift 移植到Swift。因此,它抱怨要调用该函数,但找不到它。
DevNebulae

1

我目前正在学习iOS开发,并正在阅读aPress的“ iOS6开发入门”一书。我在第10章:故事板中遇到了相同的错误。

我花了两天时间才弄清楚,但发现我不应该将TableView单元格的标签设置为1。对于其他正在编写本书并收到类似错误的人,希望对您有所帮助。

我真的希望以后代码中的错误更容易找到!哈哈哈 调试错误无济于事,无法向正确的方向发展(或者至少我太新了,无法理解调试器,哈哈)。


1

就我而言,我使用的是UIWebView,并且在第二个参数中传递了NSString而不是NSURL。因此,我怀疑传递给函数的错误类类型会导致此错误。


1

..现在我的

我将按钮链接到一个方法,该方法访问另一个按钮的参数,但是当我尝试对按钮本身进行某些操作时,效果很好,但是发生了崩溃。编译时未显示任何错误。解决方法?

我未能将按钮链接到文件的所有者。因此,如果这里有人像我一样愚蠢,请尝试:)


1

另一个略有不同的解决方案/案例。

我正在使用Xamarin和MvvmCross,并且试图将UIButton绑定到ViewModel。我将UIButton连接到一个插座和一个TouchUpInside。

绑定时,我仅使用插座:

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

我要做的就是删除XCode中的action(TouchUpInside)连接,然后解决了该问题。

附言:我想这是与先前答案特别是与@Chris Kaminski相关的所有内容,但我希望这对某人有帮助...

干杯。


1

我遇到过同样的问题。对我来说,问题是一个按钮有两种Action方法。我要做的是为按钮创建第一个操作方法,然后在视图控制器中将其删除,但是忘记在连接检查器的主故事板上断开连接。因此,当我添加第二种操作方法时,一个按钮现在有两种操作方法,这导致了错误。


1

对我来说,这是在interfacebuilder bij ctrl-dragging中创建的一个剩余连接。断开连接的名称在错误日志中

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

我有一个链接到按钮的动作。按下按钮使应用程序崩溃,因为我的代码中不再存在该插座。在日志中搜索名称使我在情节提要中找到了它。删除它,崩溃不见了!


0

我要回复Leonard Challis,因为我还参加了斯坦福iOS类C193P,用户“ oli206”也是如此

“由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:”

问题是我将计算器上的“ Enter”按钮连接了两次,一个朋友指出,检查情节提要中的按钮时,当我右键单击时,在“ Touch Up Inside”属性中有2个条目“输入”按钮。消除两个“ Touch Up Inside”“已发送事件”之一可以解决该问题。

这表明该问题被触发(对于分配1上的计算器演练中的C193P视频类)为2个已发送事件,其中一个引发了异常。


我有3个条目,一些如何。:)
1.21吉瓦

0

如果没有在InterfaceBuilder中将ViewController分配给ViewControllerScene,则可能会发生这种情况。因此,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上却无法运行,即使是完全相同的内部版本也已部署到不同的设备上。

我不明白为什么无论如何编译器都不会告诉我-问题解决了。


0

当您想将ControllerA的属性设置为自定义ControllerB类内的公共属性,并且尚未在情节提要中的身份检查器内设置“ Custom Class”时,也可能会发生这种情况。


0

我的问题和解决方案有所不同,我认为应该在这里发布,以便将来的读者免于撞墙。

我正在将不同的xib分配给相同的UIVIewController,即使在各处搜索后,我也找不到如何纠正它。然后,我检查了我的AppDelegate调用的位置initWithNibName,可以看到在复制代码时,我更改了xib名称,但是忘记更改UIViewController类。因此,如果没有一种解决方案适合您,请检查您的initWithNibName方法。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.