I believe the reason is due to how method names get mapped between Swift and Objective-C, which underlies the Cocoa implementation and the whole target/action mechanism.
In your case, the Swift method:
@objc func tapCancel(sender:UITapGestureRecognizer)
...corresponds to the Objective-C selector:
-tapCancelWithSender:
Note: In order to work with the target/action paradigm (i.e., called by means of a selector), the method needs to be declared as @objc
. The alternative attribute @IBOutlet
(for use in conjunction with Interface Builder) also supports this. (tip of the hat to @rmaddy)
In order to remove the "withSender" part and get a selector that matches tapCancel:
, you need to tell Swift to remove the argument label sender
, like this:
func tapCancel(_ sender:UITapGestureRecognizer) // Notice the underscore (_)
Also, in line with the comment by @dan, perhaps you can use:
#selector(self.tapCancel(_:))
or more succinctly, as pointed by (thanks again) @rmaddy, just:
#selector(tapCancel)
(Xcode will try to autocomplete it to #selector(tapCancel(_:))
, but the shorter syntax works as well and the method name is highlighted)
I was not familiar with the Selector()
syntax you used, so I tried playing a bit with it, and behold:
(Selector does not match any method the compiler can "see").
(After adding "withSender", the compiler can match the method, but it suggests using the better #selector(...
syntax).
As @rmaddy also pointed out in the comments, using the shorter #selector(doSomething)
syntax (no colons, no underscore, no self
) also does away with the problem of whether "withSender" is needed or not.