user6902806 user6902806 - 2 months ago 11
Swift Question

Swift 3 #selector and type names

Just updated to Xcode8 with Swift 3. Unfortunately, I am unable to add a target to a button where the target refers to a function in another class.

class AddToDoViewController {
@IBOutlet weak var doneButton: UIButton!
var st : SelectorTest!

override func viewDidLoad() {
st = SelectorTest()

st.didTapButtonHandler = {
self.doneButton.isSelected = !self.doneButton.isSelected
print("self.doneButton.selected=\(self.doneButton.isSelected)")
}

doneButton.addTarget(self, action: #selector(SelectorTest.didTapTheButton(_:)), for: .touchUpInside)
}
}


class SelectorTest {
typealias ToDoCellDidTapButtonHandler = () -> Void
var didTapButtonHandler: ToDoCellDidTapButtonHandler?

@objc func didTapTheButton(_ sender: AnyObject) {
if let handler = didTapButtonHandler {
handler()
}
}
}


In this case the target is SelectorTest.didTapButton(_:) which exists in the SelectorTest class. However when I run and click on the button I get a runtime error:

Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[Done.AddToDoViewController didTapTheButton:]:
unrecognized selector sent to instance


Since I configured the target on the button to point to

SelectorTest.didTapTheButton(_:)


which definitely exists, why am I getting a runtime error stating that it cannot find
didTapTheButton(_:)
on the AddToDoViewController? Especially when I did not specify
AddToDoViewController.didTapTheButton(_:)
as the target?

Done.AddToDoViewController didTapTheButton:


I am wondering if the
#selector
ignores the class name and assumes that the target is on the class that added the target to the button (AddToDoViewController)?

How can I set the target to
SelectorTest.didTapTheButton(_:)
and at runtime have the
SelectorTest.didTapTheButton(_:)
execute instead of the runtime attempting to fire the
AddToDoViewController.didTapTheButton(_:)
which is not the configured target and doesn't exist?

Answer

Pass the object of SelectorTest class with addTarget instead of self.

doneButton.addTarget(st, action: #selector(SelectorTest.didTapTheButton(_:)), for: .touchUpInside)

In addTarget first parameter target is type of Any?

The target object is the object whose action method is called. If you specify nil, UIKit searches the responder chain for an object that responds to the specified action message and delivers the message to that object.

Comments