“ # selector”指的是一个没有暴露在 Objective-C 中的方法

通过 addTarget 传递参数的新 Xcode 7.3通常对我有用,但是在这种情况下,它在标题中抛出了错误。有什么想法吗?当我试图将其更改为@obc 时,它会抛出另一个

谢谢!

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

它在呼叫选择器

func didTapCommentButton(post: Post) {
}
64803 次浏览

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
}

Try having the selector point to a wrapper function, which in turn calls your delegate function. That worked for me.

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

-

func wrapperForDidTapCommentButton(post: Post) {
FeedViewController.didTapCommentButton(post)
}

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.

As you know selector[About] says that Objective-C runtime[About] should be used. Declarations that are marked as private or fileprivate are not exposed to the Objective-C runtime by default. That is why you have two variants:

  1. Mark your private or fileprivate method declaration by @objc[About]
  2. Use internal, public, open method access modifier[About]