首页 文章

Objective-C中的“无法识别的选择器发送到实例”错误

提问于
浏览
137

我创建了一个按钮并为其添加了一个动作,但是一旦调用它,我就收到了这个错误:

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

30 回答

  • 2

    又一个略有不同的解决方案/案例 .

    我正在使用Xamarin和MvvmCross,我试图将UIButton绑定到ViewModel . 我把UIButton连接到Outlet和TouchUpInside .

    绑定时我只使用Outlet:

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

    我所要做的就是删除XCode中的动作(TouchUpInside)连接并解决它 .

    附:我想这是在它的基础上所有与之前的答案有关,特别是@Chris Kaminski,但我希望这有助于某些人......

    干杯 .

  • 22

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

  • 1

    我目前正在学习iOS开发,并通过aPress的“Beginning iOS6 Development”一书 . 我在第10章:故事板中得到了同样的错误 .

    我花了两天时间搞清楚,但发现我不小心将TableView单元格的标签设置为1 . 对于其他人来做这本书并收到类似的错误,我希望这会有所帮助 .

    我真的希望我的代码中的未来错误更容易找到!哈哈哈 . 调试错误并没有把我推向正确的方向来解决问题(或者至少我太新了,无法理解调试器,哈哈) .

  • 24

    在我的情况下,我使用的是UIWebView,我在第二个参数而不是NSURL中传递了一个NSString . 所以我怀疑传递给函数的错误类类型会导致此错误 .

  • 12

    看起来你没有正确管理视图控制器的内存,并且它在某些时候被解除分配 - 这导致 numberButtonClicked: 方法被发送到另一个对象,该对象现在占用了视图控制器以前占用的内存...

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

  • 0

    对于那些像我一样通过谷歌来到这里的人,这可能更适合Xcode 4.2 / iOS 5,与ARC有什么关系 . 我有同样的错误“ unrecognized selector sent to instance ” . 在我的情况下,我有一个UIButton 's target action set up to pass itself as the sender parameter, but later realised I didn' t需要它并在代码中删除它 . 所以,像:

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

    改为:

    - (IBAction)buttonPressed {
    

    右键单击有问题的UIButton,表明Touch Up Inside事件与视图控制器buttonPressed:方法相关联 . 删除它并将其重新分配给修改后的方法是一种享受 .

  • 0

    这是谷歌在这个问题上的最佳答案,但我有不同的原因/结果 - 我想我会加上我的两分钱,万一其他人偶然发现了这个问题 .

    我今天早上有类似的问题 . 我发现如果您右键单击提示问题的UI项,您可以看到已创建的连接 . 在我的情况下,我有一个按钮连接到两个动作 . 我从右键菜单中删除了操作并重新启动它们,我的问题得到了解决 .

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

  • 1

    ..现在我的

    我把按钮链接到一个方法,该方法访问了另一个按钮的参数并且工作得很好但是当我尝试用按钮本身做某事时,我遇到了崩溃 . 在编译时,没有显示任何错误 . 解决方案?

    我无法将按钮链接到文件的所有者 . 所以,如果这里的任何人像我一样愚蠢,试试这个:)

  • 0

    好的,我必须在这里筹码 . OP dynamically created the button . 我有一个类似的问题,答案(经过几个小时的狩猎)是如此简单,它让我生病了 .

    使用时:

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

    像往常一样,它总是被错过的明显答案 .

  • 0

    在我的情况下,该函数不期望参数,但按钮被配置为发送导致错误的按钮 . 为了解决这个问题,我必须重新连接事件处理程序 .

    这是我的功能:

    enter image description here

    注意它不包含任何参数 .

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

    enter image description here

    请注意,有3个事件处理程序 .

    为了解决这个问题,我不得不删除每个事件项,因为其中一个事件正在向enterPressed函数发送对它自己的引用 . 为了删除这些项目,我点击了每个项目名称旁边的小x图标,直到没有显示任何项目 .

    enter image description here

    接下来我不得不重新连接事件的按钮 . 要执行此操作,请按住Control键,然后从按钮拖动一行到操作 . 应该说“连接动作” . 注意:由于某些原因,我不得不重新启动XCode才能工作;否则它只允许我在函数的上方或下方插入动作(也就是创建一个新动作) .

    enter image description here

    您现在应该有一个事件处理程序连接到不传递任何参数的按钮事件:

    enter image description here

    这个答案与@Leonard Challis的答案相辅相成,您也应该阅读 .

  • 0

    如果未在界面生成器中设置视图的“类”,也会发生这种情况 .

  • 0

    在我的情况下,我正在使用NSNotificationCenter并尝试使用不带参数的选择器,但是添加了一个冒号 . 删除冒号修复了问题 .

    使用选择器名称时,如果没有参数,请不要使用尾随冒号 . 如果有一个参数,请使用一个尾随冒号 . 如果有多个参数,则必须为每个参数命名它们以及尾部冒号 .

    请参阅Adam Rosenfield的答案:Selectors in Objective C

  • 3

    我在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

  • 11

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

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

    我有类似的问题,但对我来说解决方案略有不同 . 在我的例子中,我使用了一个类来扩展现有的类(UIImage用于一些调整大小的功能 - 如果你're interested) and forgot to add the *.m file to the build target. Stupid error, but not always obvious when it happens where to look. I thought it'值得分享,请参阅howto ...

  • 14

    我有同样的错误,我发现了以下内容:

    当您使用代码时

    [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构建,这解决了我的问题 .

  • 1

    我认为你应该使用void,而不是返回类型的IBAction . 因为您以编程方式定义了一个按钮 .

  • 5

    我也有同样的问题 .

    我在故事板中删除了我的uibutton并重新创建它......现在一切正常 .

  • 66

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

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

    我有一个链接到按钮的动作 . 按下按钮会导致应用程序崩溃,因为我的代码中不再存在Outlet . 在日志中搜索名称会让我在故事板中找到它 . 删除它,崩溃消失了!

  • 1

    这发生在我身上,因为在我的UIViewcontroller类代码中意外删除了“@IBAction func ...”,因此在Storyboard中创建了Reference Outlet,但在运行时有任何函数可以处理它 .

    解决方案是删除属性检查器中的Outlet引用,然后重新创建它,使用命令键拖动到类代码 .

    希望能帮助到你!

  • 122

    我正在回复Leonard Challis,因为我也使用了斯坦福iOS类C193P,因为用户“oli206”

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

    问题是我在连接两次计算器上的“Enter”按钮,并且一位朋友指出在Storyboard中检查按钮显示当我右键单击时,“Touch Up Inside”属性中有2个条目“输入”按钮 . 删除两个“Touch Up Inside”中的一个“Sent Events”解决了这个问题 .

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

  • 0

    当您未将ViewController分配给InterfaceBuilder中的ViewControllerScene时,可能会发生这种情况 . 所以ViewController.m没有连接到任何场景 .

  • 2

    包括我的份额 . 我被困在这一段时间,直到我意识到我已经创建了一个禁用了ARC(Automatic counting reference)的项目 . 在该选项上快速设置为YES解决了我的问题 .

  • 1

    另一个非常愚蠢的原因是在接口(.h)中定义了选择器,但在实现(.m)中没有(p.e.typo)

  • 172

    添加到列表的另一个原因/解决方案 . 这个是由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类中的公共属性并且尚未在故事板中的身份检查器中设置“自定义类”时,也可能会发生这种情况 .

  • 0

    另一种可能的解决方案:将“-ObjC”添加到链接器参数中 .

    完整的解释如下:Objective-C categories in static library

    我认为要点是:如果类别是在静态链接的库中定义的,则链接器不够智能,无法在类别方法中进行链接 . 上面的标志在所有客观C类和类别中创建链接器链接,而不仅仅是它认为需要基于分析源的链接 . (请随意调整或纠正这个答案 . 我只是在这里鹦鹉学舌) .

  • 3

    我的问题和解决方案是不同的,我认为我应该在这里发布,以便未来的读者可以避免敲打到墙上 .

    我正在为同一个UIVIewController分配不同的xib,甚至在搜索到处之后我找不到如何纠正它 . 然后我检查了我的AppDelegate我在哪里调用 initWithNibName 并且可以看到在复制代码时,我更改了xib名称,但忘记更改 UIViewController 类 . 因此,如果解决方案都不适合您,请检查您的 initWithNibName 方法 .

  • 0

    因为约束参数冲突而发生在我身上 .

  • 1

    基础知识:动态调用

    目标C是一种动态语言,它通过查看运行时类中的方法来调用方法 . 例如,如果有 Class A 包括方法 DoSomething(arg1, arg2) . 如果你试图在 Class A 的一个对象上使用正确的参数调用该方法,一切都会正常工作 . 但是,如果参数未正确传递,例如,您只使用一个参数调用该方法,那么运行时将把它视为另一个方法的方法调用 . 最终,运行时将无法找到方法 (DoSomething with one argument) 并将通过此异常 "unrecognized selector sent to instance" .

    解决方案

    请检查 signature 对于 @selector 的预期 . 通常它就像你在代码中描述的那样

    -(IBAction)numberButtonClick:(id)sender{
    

相关问题