“Unrecognized selector sent to instance” when calling UIButton.addTarget in a class

Hi! I am trying to create a DropDownMenu class, but when I try to call addTarget to a UIButton this error comes up...

'unrecognized selector sent to instance 0x7fd167f06120' terminating with uncaught exception of type NSException'

I have been looking for the answer for hours now, and even on Stack Overflow, no one seems to have the answer. Any help is appreciated!

Here is the code for my DropDownMenu class...
Code Block
class DropDownMenu: UIView {
var main: UIButton! = UIButton(frame: CGRect(x: 0, y: 0, width: 46, height: 30))
var view: UIView!
var buttonTitles: [String]! = [""]
var titleColor: UIColor! = UIColor.black
var font: UIFont! = UIFont.systemFont(ofSize: 18)
var buttonsBorderWidth: CGFloat! = 0
var buttonsBorderColor: UIColor? = UIColor.white
var buttonsCornerRadius: CGFloat! = 0
var color: UIColor! = UIColor.clear
var buttonsImageEdgeInsets: UIEdgeInsets? = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
var images: [UIImage]? = nil
var target: UIViewController!
private var currentSelected: String? = nil
private var optionsStack = UIStackView()
init(main: UIButton) {
self.main = main
super.init(frame: CGRect())
}
func createDropDownMenu() {
main.addTarget(target, action: #selector(DropDownMenu.openDropdown(_:)), for: .touchUpInside)
print("Button Target?: \(main.allTargets), self.target: \(String(describing: target))")
let mainFrame = main.frame
optionsStack.frame = CGRect(x: mainFrame.minX, y: mainFrame.maxY, width: mainFrame.width, height: CGFloat(buttonTitles.count) * mainFrame.height)
optionsStack.axis = .vertical
view.addSubview(optionsStack)
var y: CGFloat! = 0
for title in buttonTitles {
let button = UIButton(frame: CGRect(x: 0, y: y, width: mainFrame.width, height: mainFrame.height))
button.setTitle(title, for: .normal)
button.setTitleColor(titleColor, for: .normal)
button.backgroundColor = color
button.titleLabel?.font = font
button.addTarget(target, action: #selector(DropDownMenu.onclick), for: .touchUpInside)
y += mainFrame.height
optionsStack.addArrangedSubview(button)
}
for button in optionsStack.arrangedSubviews {
button.isHidden = true
button.alpha = 0
}
}
@objc private func openDropdown(_ sender: UIButton) {
print("sender: \(String(describing: sender))")
optionsStack.arrangedSubviews.forEach { (button) in
UIView.animate(withDuration: 0.7) {
button.isHidden = !button.isHidden
button.alpha = button.alpha == 0 ? 1 : 0
self.view.layoutIfNeeded()
}
}
}
@objc private func onclick(_ sender: UIButton) {
let title = sender.titleLabel!.text
print(title as Any)
main.setTitle(title, for: .normal)
optionsStack.arrangedSubviews.forEach { (button) in
UIView.animate(withDuration: 0.7) {
button.isHidden = true
button.alpha = 0
}
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

Here is the code for the creation of the object in ViewContorller...

let main = UIButton(frame: CGRect(x: 50, y: 300, width: 80, height: 30))
main.layer.borderWidth = 1
main.setTitle("Grade", for: .normal)
main.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
main.setTitleColor(UIColor.black, for: .normal)

let gradeDP = DropDownMenu(main: main)
gradeDP.buttonTitles = ["Title 1", "Title 2", "Title 3"]
gradeDP.color = UIColor.gray
gradeDP.target = self
gradeDP.titleColor = UIColor.white
gradeDP.view = infoBox

This is all of my code...

'unrecognized selector sent to instance 0x7fd167f06120' terminating with uncaught exception of type NSException'

Usually, Xcode shows some additional info in case of unrecognized selector exception. Can't you see any outputs on the debug console of Xcode?

when I try to call addTarget to a UIButton this error comes up...

Please tell us which addTarget.


More things need to be clarified.

I cannot find any code to call createDropDownMenu(). In your shown code,addTarget is only called inside createDropDownMenu().

If you get some error when calling UIButton.addTarget, and you are sure addTarget is really called, that means this is NOT all of your code.


Please show enough info to solve your issue.




Here is the rest of my code. I forgot to add it there.
Code Block
infoBox.addSubview(gradeButton)
gradeDP.createDropDownMenu()

infoBox is just a UIView. The debugger doesn't show anything else...

The debugger doesn't show anything else...

Are you sure you activated the debug console? View > Debug Area > Activate Console


If you say the error message “Unrecognized selector sent to instance” is shown when you tap a button,
it is quite reasonable because your code has some fatal flaws in using addTarget.
But I do not understand why it is shown when calling addTarget.

Here is the rest of my code. I forgot to add it there. 

Please do not forget such an important info. You should better show the whole code of your view controller if you often forgot to add it.
On line 46

Code Block
button.addTarget(target, action: #selector(DropDownMenu.onclick), for: .touchUpInside)

Could you try with

Code Block
button.addTarget(target, action: #selector(DropDownMenu.onclick(_:)), for: .touchUpInside)

Normally that should not change behaviour, but let's check.
Thank you for trying to help me with my problem. The #selector(DropDownMenu.onclick) vs #selector(DropDownMenu.onclick(_:)) makes no difference. When I set the target to self inside of the class, it doesn't cause any error anymore, but it doesn't call the function. The error also comes up when trying to call addTarget from ViewController.
Code Block
let titleButton = UIButton(frame: CGRect(x: 100, y: 300, width: 180, height: 40))
titleButton.backgroundColor = UIColor.white
titleButton.setTitle("DropDownMenu", for: .normal)
titleButton.setTitleColor(UIColor.black, for: .normal)
titleButton.layer.borderWidth = 2
let dp = DropDownMenu(main: titleButton)
titleButton.addTarget(self, action: #selector(dp.openDropDown), for: .touchUpInside)

The error gets called when I click on the button, not when I call addTarget. The function never gets called though.

The #selector(DropDownMenu.onclick) vs #selector(DropDownMenu.onclick(_:)) makes no difference.

#selector(DropDownMenu.onclick) and #selector(DropDownMenu.onclick(_:)) are exactly the same thing unless you have another onclick(???) method.

The error gets called when I click on the button, not when I call addTarget.

Thanks for clarifying. That helps me solve your issue. But not enough.

The function never gets called though.

Please be more specific. What is the function?

I guess the function is a method of your ViewController which is not shown yet.
Have forgotten again? As I said, you should better show the whole code of your view controller .


If you write addTarget(target, #selector(...), ...), the instance held in target needs to respond to the selector.
In your code, target is an instance of your ViewController.
Does your ViewController really respond to all the selectors you have written?
Does your ViewController really need to respond to all the selectors you have written?

Anyway, you may need to clarify which method of which class you expect to be called on which event.
You have declared line 3

Code Block
var view: UIView!

Unless I missed something, the view is nowhere initialised (at least in the part of code you published)

I found this topic because I had a very similar problem. The problem in my code was two identical method names.

Once called with the button action: @IBAction func save() {..}

then in the file AppDelegate in the method saveContext in a do {} catch command: func saveContext() { ... try context.save() ... }

I renamed the button action, redo the connection and the code is now executing properly.

“Unrecognized selector sent to instance” when calling UIButton.addTarget in a class
 
 
Q