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, internalou les membres compatibles Objective-C ou supérieurs des NSObjectclasses héritières étaient déduits comme étant @objcet 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 @objcméthodes, des implémentations d' @objcexigences 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' NSObjecthé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:
class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
button.addTarget(self, action: #selector(foo), for: .touchUpInside)
}
@objc func foo() {
// ...
}
}
(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:
@objc extension ViewController {
// both exposed to Obj-C
func foo() {}
func bar() {}
}
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:
@objcMembers
class ViewController: UIViewController {
// ...
}
Maintenant, tous les membres qui peuvent être déduits le @objcseront. 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.
@objcest maintenant nécessaire pour les exposer à Obj-C, et donc les utiliser avec des sélecteurs.