J'essaie de convertir le code source de mon projet de Swift 3 à Swift 4. Un avertissement que Xcode me donne concerne mes sélecteurs.
Par exemple, j'ajoute une cible à un bouton en utilisant un sélecteur régulier comme celui-ci:
button.addTarget(self, action: #selector(self.myAction), for: .touchUpInside)
Voici l'avertissement qu'il affiche:
L'argument de '#selector' fait référence à la méthode d'instance 'myAction ()' dans 'ViewController' qui dépend de l'inférence d'attribut '@objc' obsolète dans Swift 4
Ajoutez '@objc' pour exposer cette méthode d'instance à Objective-C
Maintenant, appuyer Fix
sur le message d'erreur fait ceci à ma fonction:
// before
func myAction() { /* ... */ }
// after
@objc func myAction() { /* ... */ }
Je ne veux pas vraiment renommer toutes mes fonctions pour inclure la @objc
marque et je suppose que ce n'est pas nécessaire.
Comment réécrire le sélecteur pour gérer la dépréciation?
Question connexe:
@objc
est maintenant nécessaire pour les exposer à Obj-C, et donc les utiliser avec des sélecteurs.@objc
? C'est un peu ennuyeux, mais je rend généralement ces fonctions privées, ce qui m'oblige à le marquer de@objc
toute façon.@objcMembers
afin d'exposer tous les membres compatibles Obj-C à Obj-C, mais je ne le conseillerais pas à moins que vous n'ayez réellement besoin que votre classe entière soit exposée.Réponses:
Le correctif est correct - il n'y a rien dans le sélecteur que vous pouvez changer pour que la méthode à laquelle il se réfère soit exposée à Objective-C.
La raison de cet avertissement en premier lieu est le résultat du SE-0160 . Avant Swift 4,
internal
ou les membres compatibles Objective-C ou supérieurs desNSObject
classes héritières étaient déduits comme étant@objc
et donc exposés à Objective-C, leur permettant ainsi d'être appelés à l'aide de sélecteurs (car le runtime Obj-C est nécessaire pour rechercher la méthode implémentation pour un sélecteur donné).Cependant dans Swift 4, ce n'est plus le cas. Seules les déclarations très spécifiques sont désormais supposées être
@objc
, par exemple, des substitutions de@objc
méthodes, des implémentations d'@objc
exigences de protocole et des déclarations avec des attributs qui impliquent@objc
, tels que@IBOutlet
.La motivation derrière cela, comme détaillé dans la proposition liée ci-dessus , est tout d'abord d'éviter que les surcharges de méthodes lors de l'
NSObject
héritage de classes ne se heurtent en raison de sélecteurs identiques. Deuxièmement, cela aide à réduire la taille binaire en n'ayant pas à générer des thunks pour les membres qui n'ont pas besoin d'être exposés à Obj-C, et troisièmement, améliore la vitesse de liaison dynamique.Si vous souhaitez exposer un membre à Obj-C, vous devez le marquer comme
@objc
, par exemple:(le programme de migration doit le faire automatiquement pour vous avec des sélecteurs lors de l'exécution avec l'option «minimiser l'inférence» sélectionnée)
Pour exposer un groupe de membres à Obj-C, vous pouvez utiliser un
@objc extension
:Cela exposera tous les membres qui y sont définis à Obj-C, et donnera une erreur sur tous les membres qui ne peuvent pas être exposés à Obj-C (sauf s'ils sont explicitement marqués comme
@nonobjc
).Si vous avez une classe où vous avez besoin que tous les membres compatibles Obj-C soient exposés à Obj-C, vous pouvez marquer la classe comme
@objcMembers
:Maintenant, tous les membres qui peuvent être déduits le
@objc
seront. Cependant, je ne conseillerais pas de faire cela à moins que vous n'ayez vraiment besoin de tous les membres exposés à Obj-C, étant donné les inconvénients mentionnés ci-dessus d'avoir des membres inutilement exposés.la source
@IBAction
également automatiquement@objc
? ce n'était pas le cas jusqu'à présent mais ce serait logique. EDIT: NVM, la proposition indique clairement que cela@IBAction
suffit pour qu'une méthode soit@objc
.Comme documentation officielle Apple . vous devez utiliser @objc pour appeler votre méthode de sélection.
la source
À partir de, je pense que Swift 4.2, tout ce que vous avez à faire est d'assigner @IBAction à votre méthode et vous pouvez éviter cette annotation @objc idiote
''
la source
Comme déjà mentionné dans d'autres réponses, il n'y a aucun moyen d'éviter l'
@objc
annotation pour les sélecteurs.Mais l'avertissement mentionné dans l'OP peut être réduit au silence en prenant les mesures suivantes:
Off
ci-dessous est la capture d'écran qui illustre les étapes mentionnées ci-dessus:
J'espère que cela t'aides
la source
Si vous avez besoin de membres objectif c dans votre contrôleur de vue, ajoutez simplement @objcMembers en haut du contrôleur de vue. Et vous pouvez éviter cela en ajoutant IBAction dans votre code.
Assurez-vous de connecter cette prise dans le storyboard.
la source