“#selector”指的是不公开给Objective-C的方法

时间:2023-01-15 18:29:41

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

新的Xcode 7.3通过addTarget传递参数通常对我来说是可行的,但在这种情况下,它会在标题中抛出错误。什么好主意吗?当我试图将它改为@objc时,它会抛出另一个。

Thank you!

谢谢你!

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

The selector it's calling

选择器调用

func didTapCommentButton(post: Post) {
}

3 个解决方案

#1


124  

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

在我的例子中,选择器的函数是私有的。一旦我删除了private,错误就消失了。fileprivate也是一样。

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

在Swift 4中,需要向函数声明中添加@objc。直到斯威夫特4被暗中推断。

#2


49  

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

需要使用didTapCommentButton(_:)上的@objc属性与#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.

你说你那样做了,但你又犯了一个错误。我猜想新的错误是Post不是与Objective-C兼容的类型。如果所有的参数类型及其返回类型都与Objective-C兼容,则只能向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:

您可以通过使Post成为NSObject的子类来修复它,但这并不重要,因为didTapCommentButton(_:)的参数无论如何都不是Post。动作函数的参数是动作的发送方,那个发送方将是commentButton,这可能是一个UIButton。你应该像这样声明didTapCommentButton:

@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.

然后,您将面临这样的问题:获取与所单击的按钮对应的Post。有多种方法可以得到它。这是一个。

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:

我收集(因为您的代码是cell.commentButton)您正在设置一个表视图(或集合视图)。由于您的单元格有一个名为commentButton的非标准属性,我假设它是一个自定义的UITableViewCell子类。假设你的单元格是这样声明的后单元格

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:

然后您可以从按钮上向上走视图层次结构,找到PostCell,并从中获取post:

@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
}

#3


9  

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)
}

#1


124  

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

在我的例子中,选择器的函数是私有的。一旦我删除了private,错误就消失了。fileprivate也是一样。

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

在Swift 4中,需要向函数声明中添加@objc。直到斯威夫特4被暗中推断。

#2


49  

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

需要使用didTapCommentButton(_:)上的@objc属性与#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.

你说你那样做了,但你又犯了一个错误。我猜想新的错误是Post不是与Objective-C兼容的类型。如果所有的参数类型及其返回类型都与Objective-C兼容,则只能向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:

您可以通过使Post成为NSObject的子类来修复它,但这并不重要,因为didTapCommentButton(_:)的参数无论如何都不是Post。动作函数的参数是动作的发送方,那个发送方将是commentButton,这可能是一个UIButton。你应该像这样声明didTapCommentButton:

@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.

然后,您将面临这样的问题:获取与所单击的按钮对应的Post。有多种方法可以得到它。这是一个。

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:

我收集(因为您的代码是cell.commentButton)您正在设置一个表视图(或集合视图)。由于您的单元格有一个名为commentButton的非标准属性,我假设它是一个自定义的UITableViewCell子类。假设你的单元格是这样声明的后单元格

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:

然后您可以从按钮上向上走视图层次结构,找到PostCell,并从中获取post:

@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
}

#3


9  

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)
}