Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'#selector' refers to a method that is not exposed to Objective-C

Tags:

xcode

swift

The new Xcode 7.3 passing the parameter via addTarget usually works for me but in this case it's throwing the error in the title. Any ideas? It throws another when I try to change it to @objc

Thank you!

cell.commentButton.addTarget(self, action: #selector(FeedViewController.didTapCommentButton(_:)), forControlEvents: UIControlEvents.TouchUpInside) 

The selector it's calling

func didTapCommentButton(post: Post) { } 
like image 700
Echizzle Avatar asked Apr 24 '16 00:04

Echizzle


People also ask

Apa fungsi tanda apostrophe (') dalam bahasa indonesia apakah penggunaan ini termasuk tanda baca?

Definisi Apostrophe Merupakan sebuah tanda baca (') yang penggunaannya untuk mengidentifikasi sebuah kata benda dalam pembuatan kalimat posesif. Tanda ini bisa juga berfungsi untuk menunjukkan penghapusan dari satu atau lebih huruf dari kata yang ada di dalam sebuah kalimat.

Apa yang dimaksud dengan simbol apostrof?

Tanda penyingkat atau apostrof adalah tanda baca pada bahasa yang menggunakan alfabet Latin atau alfabet tertentu lainnya.


2 Answers

In my case the function of the selector was private. Once I removed the private the error was gone. Same goes for fileprivate.

In Swift 4
You will need to add @objc to the function declaration. Until swift 4 this was implicitly inferred.

like image 89
Shaked Sayag Avatar answered Sep 20 '22 05:09

Shaked Sayag


You need to use the @objc attribute on didTapCommentButton(_:) to use it with #selector.

You say you did that but you got another error. My guess is that the new error is that Post is not a type that is compatible with Objective-C. You can only expose a method to Objective-C if all of its argument types, and its return type, are compatible with Objective-C.

You could fix that by making Post a subclass of NSObject, but that's not going to matter, because the argument to didTapCommentButton(_:) will not be a Post anyway. The argument to an action function is the sender of the action, and that sender will be commentButton, which is presumably a UIButton. You should declare didTapCommentButton like this:

@objc func didTapCommentButton(sender: UIButton) {     // ... } 

You'll then face the problem of getting the Post corresponding to the tapped button. There are multiple ways to get it. Here's one.

I gather (since your code says cell.commentButton) that you're setting up a table view (or a collection view). And since your cell has a non-standard property named commentButton, I assume it's a custom UITableViewCell subclass. So let's assume your cell is a PostCell declared like this:

class PostCell: UITableViewCell {     @IBOutlet var commentButton: UIButton?     var post: Post?      // other stuff... } 

Then you can walk up the view hierarchy from the button to find the PostCell, and get the post from it:

@objc func didTapCommentButton(sender: UIButton) {     var ancestor = sender.superview     while ancestor != nil && !(ancestor! is PostCell) {         ancestor = view.superview     }     guard let cell = ancestor as? PostCell,         post = cell.post         else { return }      // Do something with post here } 
like image 26
rob mayoff Avatar answered Sep 22 '22 05:09

rob mayoff