2

Can anyone help me with this?

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.delegate=self
    tableView.dataSource=self
    searchBar.autocorrectionType = .yes
    searchBar.delegate=self
    searchBarView.translatesAutoresizingMaskIntoConstraints=false

    let tap:UIGestureRecognizer = UITapGestureRecognizer(target: self, action: Selector(("tapCancel:")))

    searchBarView.addGestureRecognizer(tap)
    tableView.addGestureRecognizer(tap)
    tableView.isUserInteractionEnabled=true
}
...
func tapCancel(sender:UITapGestureRecognizer){
    hideSearchBarView()
    isSearchon=false
    print("Tap cancel!")
}

Every time I tap the View, it crash. "unrecognized selector sent to instance 0x7feb85d109e0"

I will appreciate any help! Thanks!

2 Answers2

2

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:

enter image description here (Selector does not match any method the compiler can "see").

enter image description here (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.

Nicolas Miari
  • 16,006
  • 8
  • 81
  • 189
  • 1
    You just need `#selector(tapCancel)`. You do not need to add the `_` before the `sender` parameter.. And you need to add `@objc` just before `func tapCancel...` – rmaddy Jun 19 '18 at 04:59
  • @rmaddy Thank you, I’ll update the answer as soon as I get to my desk. – Nicolas Miari Jun 19 '18 at 05:00
0

use

let tap:UIGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapCancel))

instead of

let tap:UIGestureRecognizer = UITapGestureRecognizer(target: self, action: Selector(("tapCancel:")))

And add @objc before method tapCancel()

Chanchal Chauhan
  • 1,530
  • 13
  • 25