Comment puis-je composer avec @objc inférence autodérision avec #sélecteur() dans Swift 4?
Je suis en train de convertir mon projet est le code source de Swift 3 à Swift 4. Un avertissement Xcode me donne de l'est à propos de ma sélecteurs.
Par exemple, j'ai ajouter une cible à un bouton utilisant un sélecteur comme ceci:
button.addTarget(self, action: #selector(self.myAction), for: .touchUpInside)
C'est l'avertissement qu'il montre:
Argument de '#sélecteur " se réfère à la méthode d'instance 'myAction () "dans" ViewController " qui dépend de la '@objc " attribut inférence obsolète dans Swift 4
Ajouter "@objc " pour exposer cette méthode d'instance d'Objective-C
Maintenant, frapper Fix
sur le message d'erreur ne ce de ma fonction:
//before
func myAction() { /* ... */ }
//after
@objc func myAction() { /* ... */ }
Je n'ai pas vraiment envie de le renommer tous mes fonctions à inclure la @objc
marque et je suppose que ce n'est pas nécessaire.
Comment dois-je réécrire le sélecteur pour faire face à la désapprobation?
Liés à la question:
- Nope, en les marquant comme
@objc
est maintenant nécessaire afin de les exposer à l'Obj-C, et donc de l'utiliser avec des sélecteurs. - Ainsi, le obsolète partie est de déduire d'accès public fonctionne comme
@objc
? C'est un peu gênant, mais je général de rendre ces fonctions privé, m'oblige à le marquer comme@objc
de toute façon. - Voir SE-0160 pour plus d'informations sur le changement. Une autre alternative est de marquage de votre classe donnée comme
@objcMembers
afin d'exposer tous les Obj-C compatible membres de l'Obj-C, mais je ne le conseille pas, à moins que vous vraiment besoin de votre ensemble de la classe à être exposé. - Quelle serait la conséquence de cela, @Hamish? Il semble plus pratique de mettre l'ensemble de la classe à
@objc
que de le faire que pour chaque fonction individuelle. - Comme dit dans la proposition, il serait susceptible d'augmenter inutilement la taille de votre binaire et la liaison dynamique prendrait plus de temps. Je ne pense vraiment pas que c'est trop de tracas pour la clarté que vous avez spécifiquement moyenne pour une chose en particulier à être utilisé à partir de l'Obj-C.
- Alors, enveloppant: seule solution serait de marquer chaque fonction (exigeant) avec
@objc
. Si oui, poste que comme une réponse et je vais l'accepter. @Hamish. Merci pour votre aide! - essayez cette
#selector(ViewController.myAction)
- Essayé, pas de travail.
- Question connexe, qui arrive à la base: stackoverflow.com/questions/44379348/...
Vous devez vous connecter pour publier un commentaire.
Le fix-it est correct, il n'y a rien sur le sélecteur, vous pouvez modifier afin de rendre la méthode, il se réfère à l'exposé de l'Objectif-C.
La raison de cet avertissement en premier lieu est le résultat de SE-0160. Avant Swift 4,
internal
ou plus Objective-C compatible membres deNSObject
hériter de classes ont été déduites à@objc
et, par conséquent, exposés à Objective-C, ce qui permet d'être appelé à l'aide des sélecteurs (comme l'Obj-C runtime est nécessaire pour la recherche de la méthode de la mise en œuvre d'un sélecteur de donnée).Cependant dans Swift 4, ce n'est plus le cas. Très déclarations spécifiques sont maintenant déduit d'
@objc
, par exemple, des remplacements de@objc
méthodes, les implémentations de@objc
exigences du protocole et des déclarations d'attributs qui implique@objc
, comme@IBOutlet
.La motivation derrière tout cela, comme détaillé dans la proposition ci-dessus liés, est avant tout de prévenir les surcharges de méthode dans
NSObject
héritant des classes d'entrer en collision les uns avec les autres en raison de deux sélecteurs. Deuxièmement, elle permet de réduire la taille du binaire en n'ayant pas à générer des thunks pour les membres qui n'ont pas besoin d'être exposés à l'Obj-C, et, troisièmement, améliore la vitesse de la liaison dynamique.Si vous souhaitez exposer un membre de l'Obj-C, vous avez besoin de le marquer comme
@objc
, par exemple:(le migrateur devrait le faire automatiquement pour vous avec les sélecteurs lors de l'exécution avec le "minimiser l'inférence" option sélectionnée)
D'exposer un groupe de membres de l'Obj-C, vous pouvez utiliser un
@objc extension
:Cela permettra d'exposer tous les membres définis à l'Obj-C, et de donner une erreur sur tous les membres qui ne peuvent pas être exposés à l'Obj-C (sauf s'il est explicitement marqué comme
@nonobjc
).Si vous avez une classe où vous en avez besoin tous Obj-C compatible membres d'être exposés à l'Obj-C, vous pouvez marquer la classe comme
@objcMembers
:Maintenant, tous les membres qui peut être déduit d'
@objc
sera. Cependant, je ne conseille pas de faire cela, sauf si vous vraiment besoin de tous les membres exposés à l'Obj-C, compte tenu de l'mentionnés ci-dessus inconvénients de l'avoir des membres inutilement exposés.@objc
se fait@objc
. Peut-être essayer de lancer le migrateur de nouveau?@IBAction
également automatiquement@objc
? ce n'était pas le cas jusqu'à maintenant, mais il serait logique. EDIT: nvm, la proposition indique clairement que@IBAction
est suffisant pour une méthode à@objc
.@objc
a été nécessaire pourprivate
actions.@IBAction private
dans Swift 3.1@objc
fait). Sur d'autres plates-formes comme Linux, il y a aucun Obj-C de l'exécution, de sorte que vous ne peut pas, par exemple, utiliser le#selector
directive (vous pourriez considérer que ce "pur Swift")...NSObject
(qui amène tout un tas de méthodes pratiques pour interagir avec l'Obj-C runtime), Swift utilisé à supposer que vous vouliez tous (internal
ou plus) Obj-C compatible avec les membres de votre classe afin d'être exposés à l'Obj-C par défaut. Ce n'est plus le cas, vous devez spécifier les membres pour exposer (ou utilisez@objcMembers
pour exposer de nouveau).Comme Apple Documentation Officielle. vous avez besoin d'utiliser @objc pour appeler votre Sélecteur de Méthode.
Comme d', je pense que Swift 4.2, tout ce que vous devez faire est d'attribuer @IBAction à votre méthode et vous pouvez éviter cet idiot @objc annotation
``
Comme déjà mentionné dans d'autres réponses, il n'y a aucun moyen d'éviter la
@objc
annotation pour les sélecteurs.Mais avertissement mentionné dans les OP peuvent être réduits au silence en prenant les mesures suivantes:
Off
ci-dessous la capture d'écran qui illustre les étapes mentionnées ci-dessus:
Espère que cette aide
Si vous avez besoin d'objective-c les membres de votre point de vue contrôleur de simplement ajouter @objcMembers en haut de la vue-contrôleur. Et vous pouvez éviter cela en ajoutant IBAction dans votre code.
Assurez-vous de brancher cette prise en storyboard.