【问题标题】:"Unrecognized selector sent to instance" in swiftswift中的“无法识别的选择器发送到实例”
【发布时间】:2014-06-07 06:56:00
【问题描述】:

我不知道我做错了什么。我对编程也很陌生,所以我不太擅长调试。这是一个测试应用程序,因此我可以看到 swift 与应用程序开发的关系。到目前为止,我得到了这个:

class ViewController: UIViewController, UITextViewDelegate {

    var textView: UITextView!

    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        var widthField = self.view.bounds.size.width - 10
        var heightField = self.view.bounds.size.height - 69 - 221
        var textFieldString: String! = ""
        //Set up text field
        self.textView = UITextView(frame: CGRectMake(5, 64, widthField, heightField))
        self.textView.backgroundColor = UIColor.redColor()
        self.view.addSubview(self.textView)
        //Set up the New button
        var newButtonString: String! = "New Note"
        var heightButton = 568 - heightField - 1000
        let newButton = UIButton(frame: CGRect(x: 5, y: 5, width: widthField, height: 50)) as UIButton
        UIButton.buttonWithType(UIButtonType.System)
        newButton.setTitle(newButtonString,forState: UIControlState.Normal)
        newButton.backgroundColor = UIColor.redColor()
        newButton.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
        self.view.addSubview(newButton)

    }

    func buttonAction() {
        println("tapped button")
    }
}

当我在 iOS 模拟器中按下按钮时,我收到错误“无法识别的选择器已发送到实例”。该应用程序可以正常打开,但只要按下按钮,它就会崩溃。

【问题讨论】:

  • 从这个"buttonAction:" 中删除分号,因为你没有任何buttonAction 函数/选择器可以使用一个参数。您的函数使用零参数(),它们肯定是不同的。
  • 如果您将目标添加到私有函数中也会发生这种情况 - 如果有一个更强大的类型系统来捕获它会很好。
  • 致 OP:如果您看到以下答案之一有帮助并且您的问题已得到解决,请考虑通过点击投票计数器下方的复选标记来接受它。
  • 正如有人在之前的答案中所说,对我来说,问题是太多之前的 IBAction 仍然链接到该按钮Check this screenshot。在我的 Touch up inside 上有多个 IBAction。只需删除旧的并只保留您使用的那个。

标签: swift


【解决方案1】:
func buttonAction(){...

应该是

func buttonAction(sender:UIButton!)
{
    println("tapped button")
}

因为 newButton 的 action: "buttonAction:" 所以。

【讨论】:

  • 对于所有未来的 Google 员工,还请注意,使用 private func 时它不起作用。 @matsmats 说如果您包含“:”(例如"buttonAction:")也是正确的,那么您必须在调用中将发件人作为参数传递。否则,包含参数会导致方法调用失败。
  • 我在尝试将错误类型的值传递给期望 Any 的参数时遇到与 SIGABRT 类似的错误(即,我试图创建一个 .font 属性为UIFont.TextStyle.title1,导致应用崩溃)
【解决方案2】:

如果选择器名称 (buttonAction:) 中有冒号,则必须将 sender 作为 buttonAction 函数的 n 参数,如果名称中没有冒号,则不会发送 sender。

【讨论】:

  • 这个。选择器把我弄糊涂了,因为我从来不知道这一点。我认为冒号是某种 Objective-C 主义。
  • 那是冒号“:”,不是分号“;”
【解决方案3】:

通过在参数前添加“_”来实现此功能.. 请参阅下面的 sn-p

func buttonAction(sender:UIButton)  // this was throwing the error "unrecognized selector sent to instance"
{
    println("tapped button")
}

func buttonAction(_ sender:UIButton)  // added an "_ " before sender
{
    println("tapped button")
}

【讨论】:

  • 这对我也有用。这与 Swift 3 有关。
  • 工作就像一个魅力!谢谢。放_的原因是什么?
  • 在 swift 3 上工作
【解决方案4】:

我遇到的其他两个原因可能会导致此类错误:

1) 当 addTarget 的第一个参数不继承自 NSObject 时。例如,这将不起作用:

class MyClass {
    init(button: UIButton) {
        button.addTarget(
            self,
            action: Selector("onClick:"),
            forControlEvents: UIControlEvents.TouchUpInside)
    }

    func onClick(sender: AnyObject?) {
        //Gotcha!
    }
}

}

要修复,只需更改为:

class MyClass: NSObject
...

2) 当您没有使用选择器为实例保留显式引用时。例如,如果使用相同的上述代码:

func crashMe() {
    var delegate = MyClass(button)
}

即使它正在监听按钮,Swift 似乎也会垃圾收集“委托”,因此会发生崩溃。要修复,请更改为以下内容:

func crashMe() {
    self.delegate = MyClass(button)
}

在开发我的应用程序时,我还遇到了“private”和“crashMe”与“crashMe:”的问题......因此花时间写这篇文章来总结你会遇到的陷阱。 :)

【讨论】:

  • 还有一个问题,这不适用于泛型类: class FuncWrapper: NSObject { let handler: (T -> ()) init(cb: T -> ()) { handler = cb } func doHandler(b: T) { handler(b) } } class FuncWrapperButton: NSObject { let handler: (UIButton -> ()) init(cb: UIButton -> ()) { handler = cb } func doHandler (b: UIButton) { handler(b) } } 这里 FuncWrapperButton 可以是一个目标,但 FuncWrapper 不起作用
  • 没有意识到 cmets 不能包含代码!类 C:NSObject 也不能​​用作目标。
  • 谢谢谢谢谢谢!!!问题 #2 是我花费数小时追踪的错误的原因。我需要将我设置为另一个对象的委托的变量声明为实例变量而不是本地变量。
【解决方案5】:

语法应该是

@IBAction func buttonAction(_ sender: UIButton) {
     print('tapped')
 }

要么语法是问题,要么

故事板上的按钮有几个注册的动作。找出只是右键单击按钮,您应该能够看到有多少连接

如果内部修饰有多个连接,请删除一个。 这是因为如果您有多个连接并且您单击控件,编译器将会混淆它应该实现哪一个

【讨论】:

  • 我的情况是,我在情节提要中有 2 个注册动作。
【解决方案6】:

我知道现在回答这个问题为时已晚,但我正在为任何遇到类似问题的人回答这个问题。最近我遇到了一个“无法识别的选择器发送到实例”问题,这花了我一整天的时间来调试。因此,我列出了该问题的可能原因,希望这对面临此错误的人有所帮助。

通常,当您将选择器传递给实例但该选择器不存在时,会引发此错误。简而言之,就像有人给快递员一个地址,但该地址不存在。

如何调试: 1. 首先,检查所有@objc 标记的方法:当您使用#selector() 语法调用@objc 标记的方法时,方法签名应该完全相同。

  1. 当您对对象进行无效转换时,也会出现此类错误。这是我的情况。我正在将属性字符串设置为标签,并且在属性中传递了一个枚举案例(TextProperty.title)而不是(TextProperty.title.font)。所以字体变量返回一个 UIFont 对象。

由于属性中的键,字典期望“任何”Xcode 没有抛出错误。所以字体属性期待一个 UIFont 但得到了 TextProperty 枚举大小写。 因此,请检查您是否在代码中进行了无效转换。

  1. 您的代码中可能存在内存泄漏。例如:您可能正在向一个实例发送一个选择器,但该选择器已耗尽内存。

这些是我能想到的案例。如果您有什么可以帮助的,欢迎提出建议。

【讨论】:

    【解决方案7】:

    当使用performSelector() 方法时,您的方法(匹配选择器)应标记为@objc

    {  
        //...
        performSelector(Selector("myMethod"), withObject: nil, afterDelay: 0.3)
        //...
    
        // or in swift 2.2
        performSelector(#selector(ClassName.myMethod), withObject: nil, afterDelay: 0.3)
        //
    
        // or in swift 3
        perform(#selector(ClassName.myMethod), with: nil, afterDelay: 0.3)
        //
    
    }
    
    @objc private func myMethod() { }
    

    【讨论】:

    • 哇,我只是在绝望中尝试了这个,没想到它会起作用,但它确实起作用了!谢谢!我只是不明白为什么这应该是必要的(尤其不是因为我确定我的代码昨天没有 @objc 前缀,但今天由于某种未知原因停止了这样做)。
    • @LukasKalinski @objc 如果您将方法标记为private,则可能需要
    【解决方案8】:

    在代码中添加@IBAction 函数,然后在不更新情节提要的情况下删除或重命名它也会导致此错误。

    查看错误信息中的选择器:

    '-[HelloWorld.ViewController yourActionFunction:]: unrecognized selector sent to instance 0x157e0c830'
                                 ^^^^^^^^^^^^^^^^^^
    

    你有一个名为yourActionFunction 的函数吗?如果没有,请选择情节提要并编辑控件上的连接(例如按钮)。

    【讨论】:

      【解决方案9】:

      在您的 viewDidLoad 中,请注意我的 Selector 正在使用冒号调用我的 func。

      override func viewDidLoad() {
              super.viewDidLoad()
              // init gesture recognizer swipe right vars
              var rightSwipe = UISwipeGestureRecognizer(target: self, action: Selector("gestureFunc:"))
              rightSwipe.direction = UISwipeGestureRecognizerDirection.Right
              view.addGestureRecognizer(rightSwipe) 
          }
      

      然后确保 Selector 即 func 已准备好接收它的滑动:

              // selector from UISwipeGestureRecognizer
              func nextWeapon(gesture: UISwipeGestureRecognizer) {
              println("swipe right")
              }
      

      【讨论】:

        【解决方案10】:

        对于最终和我一样的人:如果您在静态上下文中创建按钮,请确保将正确的目标传递给 UIButton.addTarget(_:action:for:)。传递self 将导致传递类型而不是实例。

        【讨论】:

          【解决方案11】:

          在某些情况下要修复它,您需要转到 Build Settings -> Other Linker Flags,然后将其值设置为 -ObjC

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-06-16
            • 1970-01-01
            • 2018-04-24
            相关资源
            最近更新 更多