【问题标题】:"unrecognized selector sent to instance" error in Objective-CObjective-C 中的“无法识别的选择器发送到实例”错误
【发布时间】:2023-03-19 14:29:01
【问题描述】:

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

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

【问题讨论】:

标签: objective-c selector unrecognized-selector


【解决方案1】:

看起来您没有正确管理视图控制器的内存并且它在某个时候被释放 - 这导致 numberButtonClicked: 方法被发送到另一个对象,该对象现在占用视图控制器之前的内存占领……

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

【讨论】:

  • 这是一个非常精明的诊断,只需几行代码。
  • 好的,问题已经确定了……但是“请确保您正确地保留/释放您的视图控制器。”是建议,而不是解决方案。
  • @alex gray,什么?视图控制器上的适当内存管理解决了这个问题......我不明白这不是一个解决方案吗?
  • 正确。虽然这似乎是“修复”..我可能是少数,(尽管我仍然设法存在),但问题和解决方案之间的联系并不是立即显而易见的。例如,我遇到了-[NSWindow end]: unrecognized selector sent to instance 0x100523e80,虽然我意识到与 OP 的相似之处,甚至可能是您的回答中出现问题的原因,但修复的实施并不是很明显
  • 显而易见。您的 NSWindow 内存管理沿线某处不正确。完成它的生命周期并纠正它。
【解决方案2】:

对于那些像我一样通过 Google 来到这里的人,这可能更多地与 Xcode 4.2+/iOS 5+ 相关,与 ARC 有什么关系。我遇到了同样的错误“无法识别的选择器发送到实例”。在我的情况下,我设置了一个 UIButton 的目标操作以将其自身作为 sender 参数传递,但后来意识到我不需要它并在代码中将其删除。所以,像:

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

改为:

- (IBAction)buttonPressed {

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

【讨论】:

  • 这很有帮助,尽管我认为它自己的问题和回答会更容易找到。
  • @LeonardChallis 如果未将其作为参数传递,您如何在 buttonPressed 中引用发件人?
  • 非常有帮助的回复。我刚刚遇到了这个确切的问题,您的解决方案是完全正确的。发生这种情况时,正在关注 iTunesU 上的斯坦福 iOS 课程。再次感谢您的回答!
  • @LeonardChalis 谢谢。我为你的回答添加了一个免费的答案。
  • 我只是在为类似的问题而苦苦挣扎,从选择器函数中删除了 sender 参数,然后想知道如何获取 sender。在我的情况下,我收到错误是因为我忘记在选择器回调后放置一个冒号,从而导致调用序列不匹配。使用冒号,我可以保留 sender 参数。
【解决方案3】:

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

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

所以请确保你的操作是正确的。

【讨论】:

  • 这是我的问题。我重命名了一个函数并更改了我的代码,但没有更改 xib 文件中的连接。
  • 谢谢!原来我有三个我删除的方法仍然被引用。困扰我一个星期!
【解决方案4】:

好的,我必须在这里筹码。 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");
}

像往常一样,总是错过明显的答案。

【讨论】:

  • 非常感谢!这是我的问题(没有在选择器名称的末尾加上冒号“:”)。为什么几乎总是最愚蠢的简单事情让我们这些极客在凌晨 3 点用头撞墙?非常感谢!
【解决方案5】:

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

这是我的功能:

注意它不包含任何参数。

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

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

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

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

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

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

【讨论】:

    【解决方案6】:

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

    【讨论】:

    • 啊,谢谢!这导致我的应用程序在 segue 上崩溃,只是忘记设置控制器的类。
    • 为什么需要知道类?我正在尝试将 UITableViewSection 用作 UIView,因此出现此错误。编译器说 UITableViewSection 不存在,所以我假设它是 UIKit 内部的。
    【解决方案7】:

    就我而言,我使用的是 NSNotificationCenter 并尝试使用不带参数但添加冒号的选择器。删除冒号解决了这个问题。

    使用选择器名称时,如果没有参数,请勿使用尾随冒号。如果有一个参数,请使用一个尾随冒号。如果有多个参数,则必须为每个参数命名,并在后面加上一个冒号。

    在此处查看 Adam Rosenfield 的答案:Selectors in Objective-C?

    【讨论】:

      【解决方案8】:

      我在动态创建按钮的 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
      【解决方案9】:

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

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

      【讨论】:

      • 这是一个很好的提示 - 不子类化视图或数据对象(例如,未能添加子类名称)是发生这种情况的另一种方式
      【解决方案10】:

      我也遇到了同样的问题。

      我删除了情节提要中的 uibutton 并重新创建了它.. 现在一切正常。

      【讨论】:

        【解决方案11】:

        我遇到了类似的问题,但对我来说解决方案略有不同。就我而言,我使用 Category 来扩展现有类(UIImage 用于一些调整大小的功能 - 如果您有兴趣,请参阅此 howto)并忘记将 *.m 文件添加到构建目标。愚蠢的错误,但当它发生在哪里看时并不总是很明显。我觉得值得分享...

        【讨论】:

          【解决方案12】:

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

          完整的解释在这里:Objective-C categories in static library

          我认为要点是:如果类别是在您静态链接的库中定义的,则链接器不够聪明,无法链接类别方法。上面的标志使链接器链接到所有目标 C 类和类别中,而不仅仅是它认为基于分析您的源代码需要的链接器链接。 (请随意调整或更正该答案。我知道链接语言,所以我只是在这里鹦鹉学舌)。

          【讨论】:

            【解决方案13】:

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

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

            希望对你有帮助!

            【讨论】:

            • 同样,当按钮引用一个不再存在的函数时,我也发生了这种情况。
            【解决方案14】:

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

            【讨论】:

              【解决方案15】:

              我遇到了同样的错误,我发现了以下问题:

              当你使用代码时

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

              你可能认为它在寻找选择器:

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

              但它实际上是在寻找选择器:

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

              那个选择器不存在,所以你会崩溃。

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

              但是,如果您有其他调用刷新函数的函数 没有提供发送者呢?您需要一种对两者都适用的功能。简单的解决方案是添加另一个功能:

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

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

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

              我还在一台无法升级到最新版 Mac OSX 的旧 Mac 上学习斯坦福 iOS 课程。所以我仍在为 iOS 6.1 构建,这解决了我的问题。

              【讨论】:

                【解决方案16】:

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

                发件人(tabBar 项)没有任何引用出口。所以它没有指向任何地方。

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

                希望对大家有所帮助。

                【讨论】:

                • 只是补充一下,就我而言,我忘记将IBAction 移植到Swift。所以它抱怨它想调用那个函数,但是找不到。
                【解决方案17】:

                如何调试“无法识别的选择器发送到实例”

                在大多数情况下,Xcode 不会将我们带到发生此问题的确切位置。当应用程序崩溃时,您将看不到导致这种情况的代码行,而是将您带到 App 委托类,错误输出如下:

                [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:]
                

                你也可以为所有异常设置断点。 现在再次运行您的代码。这一次,当这个异常发生时会触发断点。

                作者:Prafulla Singh

                完整解释:https://prafullkumar77.medium.com/how-to-debug-unrecognized-selector-send-to-instance-402473bc23d

                【讨论】:

                  【解决方案18】:

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

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

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

                  【讨论】:

                    【解决方案19】:

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

                    【讨论】:

                      【解决方案20】:

                      ..现在是我的

                      我将按钮链接到一个方法,该方法访问另一个按钮的参数并且效果很好,但是当我尝试对按钮本身做一些事情时,我遇到了崩溃。编译的时候没有报错。。解决办法?

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

                      【讨论】:

                        【解决方案21】:

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

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

                        装订时我只使用插座:

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

                        我所要做的就是删除 XCode 中的操作 (TouchUpInside) 连接,然后就解决了。

                        附: 我想这与以前的答案有关,尤其是与@Chris Kaminski 有关,但我希望这对某人有所帮助...

                        干杯。

                        【讨论】:

                          【解决方案22】:

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

                          【讨论】:

                            【解决方案23】:

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

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

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

                            【讨论】:

                              【解决方案24】:

                              我正在回复 Leonard Challis,因为我也参加了斯坦福 iOS 课程 C193P,用户“oli206”也是如此

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

                              问题是我将计算器上的“Enter”按钮连接了两次,一位朋友指出,当我检查 Storyboard 中的按钮时,发现有 2 个条目位于“Touch Up Inside”属性上右键单击“Enter”按钮。删除两个“Touch Up Inside”“已发送事件”之一解决了这个问题。

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

                              【讨论】:

                              • 我有 3 个条目。 :)
                              【解决方案25】:

                              当您没有将 ViewController 分配给 ViewControllerScene 时,可能会发生这种情况 界面生成器。所以 ViewController.m 没有连接到任何场景。

                              【讨论】:

                                【解决方案26】:

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

                                【讨论】:

                                  【解决方案27】:

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

                                  【讨论】:

                                    【解决方案28】:

                                    添加到列表的另一个原因/解决方案。这是由 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 上运行良好,即使是完全相同的构建部署到不同的设备。

                                    我不明白为什么编译器不能告诉我这个,无论如何 - 问题已解决。

                                    【讨论】:

                                      【解决方案29】:

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

                                      【讨论】:

                                        【解决方案30】:

                                        我的问题和解决方案不同,我想我应该把它贴在这里,这样未来的读者就可以免于碰壁。

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

                                        【讨论】:

                                          猜你喜欢
                                          • 1970-01-01
                                          • 2014-08-03
                                          • 1970-01-01
                                          • 1970-01-01
                                          • 2012-04-04
                                          • 1970-01-01
                                          • 1970-01-01
                                          • 1970-01-01
                                          相关资源
                                          最近更新 更多