7

I am having problems with trying to get a UIButton to work when the user presses it. I keep getting an error saying: unrecognised selector sent to instance

override func viewDidLoad() {
    super.viewDidLoad()

    button.addTarget(self, action: "buttonClick", forControlEvents: UIControlEvents.TouchUpInside)
    button.setTitle("Print", forState: UIControlState.Normal)
    button.font = UIFont(name: "Avenir Next", size: 14)
    button.backgroundColor = UIColor.lightGrayColor()
    self.view.addSubview(button)
}

func buttonClick(Sender: UIButton!)
{
    myLabelInfo.text = "Hello"
}

For a Swift method such as func buttonClick(Sender: UIButton) what is the correct string to pass to addTarget method for the selector? Is it "buttonClick", "buttonClick:", "buttonClickSender:" or something else?

progrmr
  • 75,956
  • 16
  • 112
  • 147
Stephen Fox
  • 14,190
  • 19
  • 48
  • 52
  • 2
    Nice to know you got an error. Did it occur to you to actually *quote* the error message?? – Hot Licks Jun 11 '14 at 00:56
  • @HotLicks To be fair, 'unrecognized selector sent to instance' is a pretty common and easy error to troubleshoot. It's kind of like saying "I got a null reference error", we can pretty much figure out what happened. – Erik Jun 11 '14 at 02:41
  • 2
    try `"buttonClick:" (extra colon) – Bryan Chen Jun 11 '14 at 03:42
  • @SiLo - But it's a lot easier to diagnose with the actual message, since it tells you precisely what you did wrong. – Hot Licks Jun 11 '14 at 03:45

6 Answers6

23

You're using an invalid method signature for the action. You're supplying buttonClick, but the method has an argument, so the signature should be buttonClick:

button.addTarget(self, action: "buttonClick:", forControlEvents: UIControlEvents.TouchUpInside)

For more information about how to format your selectors, you can refer to the accepted answer in the post linked below. The code used in this post may be Objective-C, but all its lessons can be applied here as well.

Creating a selector from a method name with parameters

And as a side note, this code would also be valid if you used Selector("buttonClicked:") as the action, but you don't have to because string literals can be implicitly cast to the Selector type.

Quoting from Using Swift with Cocoa and Objective-C

An Objective-C selector is a type that refers to the name of an Objective-C method. In Swift, Objective-C selectors are represented by the Selector structure. You can construct a selector with a string literal, such as let mySelector: Selector = "tappedButton:". Because string literals can be automatically converted to selectors, you can pass a string literal to any method that accepts a selector.

Community
  • 1
  • 1
Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281
11

Swift < 2.2

In Swift < 2.2 the selector method cannot be private (unrecognized selector error).

Prefered (by Apple) notation is the string "methodWithParam:" notation.

Troubleshooting: if you have troubles with NSTimer selector, maybe your class should be a subclass of NSObject.

Swift >= 2.2

Use the #selector notation. Read more here: https://github.com/apple/swift-evolution/blob/master/proposals/0022-objc-selectors.md

For private methods you can use the @objc method modifier, like this: @objc private func timerTick(timer: NSTimer).

No need for subclassing NSObject anymore!

Tomasz Wójcik
  • 955
  • 10
  • 23
3

The notation for Swift > 2.2 would be:

let longPress = UILongPressGestureRecognizer(target: self, action: #selector(YourClass.yourMethod(_:)))

Worked for me so far (Xcode 7.3)

MkaysWork
  • 625
  • 1
  • 7
  • 11
2

You need to pass it an actual Selector. Try using this line instead:

button.addTarget(self, action: Selector("buttonClick:"), forControlEvents: UIControlEvents.TouchUpInside)

You also need the : at the end of the selector name because you have 1 argument. This is the same as typical Obj-C selector naming.

Erik
  • 12,730
  • 5
  • 36
  • 42
0

You have missed the colon while specifying selector.so the line should be

button.addTarget(self, action: Selector("buttonClick:"), forControlEvents: UIControlEvents.TouchUpInside)

saran
  • 404
  • 2
  • 4
  • 9
0

I had the same problem - the solution ended up being prefixing the method I wanted the button to execute on click with @objc, to expose it in the Objective-C header file and thereby the Objective-C runtime.

Like:

@objc func buttonClick(Sender: UIButton!)
{
    myLabelInfo.text = "Hello"
}
micmdk
  • 951
  • 1
  • 8
  • 12