2014-06-09 2 views
23

Pour la plupart, Swift est une énorme amélioration par rapport à Objective-C en termes de sécurité de type. Une exception flagrante est celle des sélecteurs. En Objective-C, l'utilisation de l'expression donnera un avertissement du compilateur. L'équivalent Swift, Selector("notARealSelector:") sera toujours compiler mais échouera à l'exécution.Existe-t-il un moyen sûr d'utiliser les sélecteurs dans Swift?

Existe-t-il un moyen sûr d'utiliser des sélecteurs dans Swift, afin que je puisse travailler avec les API Objective-C qui en ont besoin?

J'ai beaucoup de NSNotification observateurs dans mon application et je voudrais avoir une sorte de vérification à la compilation que je ne fais pas de fautes de frappe dans mes sélecteurs.

Édition: Le cas d'utilisation spécifique est NSNotificationCenter.addObserver.

+0

Pouvez-vous donner un exemple de la façon dont vous utilisez le '@selector()' bloque-t-il actuellement? Est-ce que les objets que vous appelez ces méthodes s'exposent (soit par la conformité du protocole, soit par le sous-classement) aux méthodes à tout moment? Vous pouvez utiliser 'myDelegate? .scrollViewDidScroll? (...)', mais cela nécessite que le délégué se conforme au moins au protocole afin que le compilateur ait une chance de déterminer s'il est possible que cette méthode soit là. –

+0

Comme je l'ai dit dans la question, 'NSNotificationCenter.addObserver' – Bill

+0

Une autre utilisation courante de @selector est la cible/action utilisée par' UIControl' et ses sous-classes. par exemple. 'button.addTarget (self, action:" doTap ", forControlEvents: .TouchUpInside)' - frustrant que le compilateur rapide ne puisse pas avertir des erreurs dues aux fautes de frappe ou aux noms de méthodes changeant. –

Répondre

3

sélecteurs Typesafe ont été libérés juste dans Xcode 7.3 beta 4:

let sel = #selector(insertSubview(_:aboveSubview:)) // sel has type 

Selector est maintenant un citoyen de première classe et est livré avec quelques bons avertissements du compilateur Swift. Si nécessaire, vous pouvez toujours passer dans une chaîne:

let sel = Selector("propertyName") 

Voir beaucoup plus complète réponse ici: @selector() in Swift?

Xcode Release Notes: http://adcdownload.apple.com/Developer_Tools/Xcode_7.3_beta_4/Xcode_7.3_beta_4_Release_Notes.pdf

+0

Excellent - merci de me le faire savoir! – Bill

+1

@Bill Voir aussi ma discussion ici: http://stackoverflow.com/a/35658335/341994 Ceci explique en détail la nouvelle syntaxe '# selector'. Il leur a seulement fallu deux ans pour que vous posiez (à juste titre) votre question pour trouver cela ... :) À mon avis, ce trou dans la sécurité de type a été, tout ce temps, une contradiction massive de tout ce qui Swift est censé représenter. Maintenant, le trou a été rempli. – matt

1

Utilisez la notion de Swift optionals comme:

if let result = object.notARealSelector?(/* args */) { 
    // Use Result 
} 

où le ? utilisé suivant notARealSelector avec le retour false à if lorsqu'une telle méthode n'est pas définie sur le type object.

Il y a une mise en garde pour optional protocol requirements:

exigences du Protocole facultatif ne peuvent être spécifiés si votre protocole est marqué avec l'attribut @objc. Même si vous n'interagissez pas avec Objective-C, , vous devez marquer vos protocoles avec l'attribut @objc si vous souhaitez spécifier les exigences facultatives .

Mais puisque vous demandez des méthodes optionnelles en premier lieu, vous devez en parler dans le contexte Objective-C.

+0

Oui, comme je l'ai dit dans la question, j'essaie de passer des sélecteurs à 'NSNotificationCenter' – Bill

+2

En outre, le traitement d'une fonction en option ne fonctionne que pour les méthodes de protocole facultatives - vous ne pouvez pas faire 'object.notARealSelector' sauf si' object' est une variable/constante de type protocole et que ce protocole est un protocole '@ obcj' qui déclare' notARealSelector' en tant que méthode '@ optional'. – rickster

-1

Vous pouvez utiliser la réflexion pour obtenir les noms des propriétés d'un objet en tant que chaînes, comme résumé dans this answer, mais cela ne fera pas la connexion entre un identificateur et son nom de chaîne comme le fait @selector dans ObjC. Une utilisation créative de la réflexion pourrait contourner ce problème, mais vous pourriez aussi bien faire file a bug.

Questions connexes