web-dev-qa-db-fra.com

Comprendre Swift 2.2 Syntaxe du sélecteur - #selector ()

Je bascule la syntaxe de mon projet vers Swift 2.2 (que xCode m'aide à faire automatiquement)); cependant, je ne comprends pas la nouvelle syntaxe #selector().

Par exemple:

timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, 
             selector: #selector(MyVC.timerCalled(_:)), //new selector syntax!
             userInfo: nil, repeats: true)

Ceci a le sélecteur #selector(MyVC.timerCalled(_:))

Que signifie le _:? Pouvez-vous ajouter d'autres variables dans ce sélecteur? Dites, #MyVC.timerCalled(_:whateverVar).

Les informations générales sur ce qui est différent dans cette syntaxe, par opposition à l'implémentation basée sur des chaînes de versions précédentes de Swift, sont grandement appréciées.

36
Anthony Dito

Le bit entre parenthèses est un mécanisme permettant d'identifier la liste d'arguments du sélecteur souhaité.

Je vous recommande d’examiner la proposition désignation généralisée de Swift Evolution). Elle couvre les cas où plusieurs fonctions ne diffèrent que par leurs libellés de paramètres et doivent être référencées. L’exemple de ce document est:

extension UIView {
  func insertSubview(view: UIView, at index: Int)
  func insertSubview(view: UIView, aboveSubview siblingSubview: UIView)
  func insertSubview(view: UIView, belowSubview siblingSubview: UIView)
}

Si vous voulez obtenir une valeur de fonction pour l'une d'entre elles, le résultat est ambigu:

let fn = someView.insertSubview // ambiguous: could be any of the three methods

La solution implémentée consiste à ajouter les étiquettes d'arguments, sans aucune information de type, au code qui génère la valeur de fonction pour désambiguïser:

let fn = someView.insertSubview(_:at:)
let fn1 = someView.insertSubview(_:aboveSubview:)

Voyez comment les étiquettes sont ajoutées dans les parenthèses?

Cette proposition a joué un rôle dans celui qui s'applique le plus directement à votre question:

référençant le sélecteur Objective-C d'une méthode

Dans ce cas particulier, le sélecteur auquel vous voulez faire référence est timerCalled: qui est une fonction d’un paramètre qui n’a pas de libellé. Par conséquent (_:). Le trait de soulignement signifie que l'étiquette n'est pas spécifiée et les deux points.

31
Scott Thompson

Swift 2.2 désapprouve les sélecteurs Stringified: In Swift 2.0, nous écrivions le sélecteur sous forme de chaîne, c'est-à-dire "buttonClicked". L'inconvénient de cette approche est que le compilateur ne peut pas vérifier si la méthode existe vraiment ou non au moment de la compilation (même si vous l'avez mal orthographiée).

EX: 1

func buttonClicked(){
}

Ainsi, la méthode ci-dessus dans la nouvelle approche peut être appelée #selector(buttonClicked)

EX: 2

func buttonClicked(stringValue : String){
}

Ainsi, la méthode ci-dessus dans la nouvelle approche peut être appelée #selector(buttonClicked(_:))

EX:

func buttonClicked(stringValue : String, indexValue : Int){
}

Ainsi, la méthode ci-dessus avec des paramètres dans la nouvelle approche peut être appelée #selector(buttonClicked(_:indexValue:))

19
Durga Vundavalli

Considérez le code ci-dessous pour ajouter la cible au bouton dans Swift 3 en utilisant #selector

button.addTarget(self, action: #selector(self.buttonAction(sender:)),
                       for: UIControlEvents.touchUpInside)

 func buttonAction(sender:UIButton!){

 }

Cette syntaxe a fonctionné pour moi lors de la migration vers Swift 3

9
Ankit

C’est ainsi que les signatures de méthodes Swift sont représentées dans la documentation et qu’elles commencent à être utilisées dans de nouvelles fonctionnalités de langage telles que la syntaxe #selector() pour exprimer les méthodes par leur argument) des listes.

Chaque deux points (:) Représente un paramètre de méthode. Pour les paramètres nommés, les deux points sont précédés du nom du paramètre externe; pour les paramètres non nommés, un trait de soulignement (_) est utilisé.

Ainsi, par exemple, MyVC.timerCalled(_:)) indique une méthode sur le type MyVC avec un paramètre non nommé, qui pourrait être déclaré comme ceci:

func timerCalled(timer: NSTimer) { ... }

(Notez que timer est le nom du paramètre interne car, par défaut, le premier paramètre d'une méthode n'est pas nommé.)

Le type (MyVC dans votre exemple) peut également être omis s'il se trouve dans le même champ d'application de la déclaration #selector().

Un exemple plus complexe pourrait ressembler à ceci:

let sel = #selector(aMethodWithSeveralParameters(_:secondParam:thirdParam:))

...

func aMethodWithSeveralParameters(firstParam: Int, secondParam: Int, thirdParam: Int) { ... }
8
Stuart