web-dev-qa-db-fra.com

'#selector' fait référence à une méthode qui n'est pas exposée à Objective-C

Le nouveau Xcode 7.3 qui transmet le paramètre via addTarget fonctionne généralement pour moi, mais dans ce cas, l'erreur renvoie le titre. Des idées? Il en jette un autre quand j'essaie de le changer en @objc

Je vous remercie!

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

Le sélecteur il appelle

func didTapCommentButton(post: Post) {
}
100
Echizzle

Dans mon cas, la fonction du sélecteur était private. Une fois que j'ai enlevé le private l'erreur était partie. Il en va de même pour fileprivate.

Dans Swift 4
Vous devrez ajouter @objc à la déclaration de fonction. Jusqu'au Swift 4, cela était implicitement déduit.

168
Shaked Sayag

Vous devez utiliser l'attribut @objc sur didTapCommentButton(_:) pour l'utiliser avec #selector.

Vous dites que vous avez fait cela, mais vous avez une autre erreur. Je suppose que la nouvelle erreur est que Post n’est pas un type compatible avec Objective-C. Vous ne pouvez exposer une méthode à Objective-C que si tous ses types d'argument, ainsi que son type de retour, sont compatibles avec Objective-C.

Vous pouvez résoudre ce problème en faisant de Post une sous-classe de NSObject, mais cela n’a aucune importance, car l’argument de didTapCommentButton(_:) ne sera de toute façon pas un Post. L'argument d'une fonction d'action est le expéditeur de l'action, et cet émetteur sera commentButton, ce qui est vraisemblablement un UIButton. Vous devriez déclarer didTapCommentButton comme ceci:

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

Vous aurez alors le problème d'obtenir le Post correspondant au bouton tapoté. Il y a plusieurs façons de l'obtenir. En voici un.

Je suppose (puisque votre code dit cell.commentButton) que vous configurez une vue de table (ou une vue de collection). Et puisque votre cellule a une propriété non standard nommée commentButton, je suppose que c'est une sous-classe personnalisée UITableViewCell. Supposons donc que votre cellule est une PostCell déclarée ainsi:

class PostCell: UITableViewCell {
    @IBOutlet var commentButton: UIButton?
    var post: Post?

    // other stuff...
}

Ensuite, vous pouvez remonter la hiérarchie de vues à partir du bouton pour trouver le PostCell, et en tirer le 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
}
54
rob mayoff

Essayez de faire pointer le sélecteur sur une fonction wrapper, qui à son tour appelle votre fonction de délégué. Cela a fonctionné pour moi.

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

-

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