46 votes

L'argument de '#selector' ne fait pas référence à une méthode, une propriété ou un initialisateur '@objc'.

J'ai sublcassé dans Swift 3 une UIButton qui est écrite en Objective-C.

Lorsque j'essaie d'ajouter une cible, cela échoue avec un code d'erreur :

class ActionButton: JTImageButton {

    func action() {

    }

    func configure()) {
        // ...
        self.addTarget(self, action: #selector(self.action()), for: .touchUpInside)
        // error: 
        // Argument of '#selector' does not refer to an '@objc' method, property, or initializer

    }
}

75voto

matt Points 60113

Le problème est qu'en #selector(self.action()) , self.action() est un appel de méthode . Vous ne voulez pas appelez la méthode ; vous voulez nom la méthode. Disons #selector(action) à la place : on perd les parenthèses, et on n'a pas besoin de l'élément self .

44voto

cjrieck Points 664

Tout ce que vous avez à faire est de marquer le func en tant que @objc et il n'y a pas besoin de la self ou la parenthèse

class ActionButton: JTImageButton {

    @objc func btnAction() {

    }

    func configure() {
        // ...
        self.addTarget(self, action: #selector(btnAction), for: .touchUpInside)
        // error: 
        // Argument of '#selector' does not refer to an '@objc' method, property, or initializer

    }
}

Vous pouvez même le faire private si vous voulez

12voto

Victor John Points 332

Ajout de @objc mot-clé dans l'avant la méthode qui est parfait, mais j'ai toujours obtenu cette erreur. Finalement, j'ai trouvé la solution comme suit enter image description here

Il y a une paire de parenthèses superflues derrière la méthode, comme le montre l'image ci-dessus. Ce que je dois faire, c'est l'enlever et cela a bien fonctionné.

2voto

dfd Points 5035

Ajouté à partir des commentaires sur une autre réponse : func action() n'est pas seulement un mauvais choix pour le nom et l'action d'une fonction, il ne se construit pas. (Vous pouvez cependant l'utiliser comme paramètre de fonction d'entrée, ce que je fais par souci de clarté lorsque je passe la cible/action à un init() qui définit ces choses). Je le remplace par MonAction() pour plus de clarté.


Essayez ça :

self.addTarget(self, action: #selector(MyAction), for: .touchUpInside)

Cela dit, une meilleure conception consiste à déplacer la fonction MyAction() vers la vue supérieure du bouton, car cela rend les choses plus conformes à la conception MVC de base :

Supervision :

let myButton = ActionButton()
// include other button setup here
myButton.addTarget(self, action: #selector(MyAction), for: .touchUpInside

func action(_ sender: ActionButton) {
    // code against button tap here
}

Un codage alternatif pour ceci, en gardant la méthode "action()" dans le contrôleur de vue mais en déplaçant seulement le "addTarget" dans le bouton :

self.addTarget(superview?, action(superview?.MyAction), for: .touchUpInside)

Pourquoi est-ce que je vous demande d'envisager de déplacer la méthode "MyAction()" vers la vue supérieure ? Pour deux raisons :

  • Il contrôle non seulement le bouton, mais aussi toutes les autres sous-vues dans sa vue et elles interagissent généralement entre elles via le contrôleur de vue.
  • Cela rend le bouton beaucoup plus réutilisable dans d'autres scénarios.

1voto

Bawpotter Points 888

Au lieu de dire self.action() utiliser ActionButton.action() .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X