Autocompletion avec Swift
yoann
Membre
Bonjour tout le monde,
Je suis en train de faire une appli test sur iOS 8 et je me suis dis que j'allais tester en Swift vu que tout le monde dit que c'est mature.
Et forcément, j'ai des truc incohérent.
Entre autre sur l'autocompletion, je comprends pas.
Je commence à tapper :
NSNotificationCenter.post
Puis je fais esc pour avoir l'autocompletion, le popup me propose bien les trois méthodes même si la présentation est à chier.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Parce ça n'est pas une méthode de classe...
ça, ça fonctionnera mieux :
De manière générale, avec Swift, quand tu vois self dans l'auto-complétion c'est que tu essaie d'appeller une méthode d'instance comme une méthode de classe.
En effet, erreur de ma part.
Enfin du coup la question reste. Pourquoi cet abruti me propose à l'autocompletion des éléments qui n'existent pas ?
T'as essayé sans le traiter d'abruti, ni d'andouille ?
Parce que si le langage et le compilo sont peut-être matures les outils de dev ont encore besoin d'un peu de temps.
Xcode est encore un peu con-con quand on lui parle de Swift. Au moins il ne crash plus toutes les 18 secondes...
En Swift (comme dans d'autres langages qui supportent cette feature), une méthode d'instance est aussi une méthode de classe qui prend self en argument et retourne la méthode d'instance associée (Currying).
ça peut s'avérer très pratique par exemple pour passer en paramètre une méthode d'instance qui sera appliquée plus tard mais tu ne sais pas encore sur quelle instance (en passant la méthode de classe currified sous forme de closure en paramètre) ; très adapté pour la programmation fonctionnelle par exemple.
ça te permet de faire des choses qu'en Objective-C tu ferais en passant un @selector et en faisant ensuite une NSInvocation ou un performSelector: sur l'instance... sauf qu'en utilisant la currification de la méthode d'instance comme étant une application (au sens mathématique) d'une méthode de classe sur self, tu as en bonus la vérification syntaxique qui est toujours présente et les contrôles du compilateur qui te permettent de garder une cohérence des domaines d'application de tes méthodes.
Tu aurais un exemple de code Swift pour ça ?
Je ne vois pas trop à quel moment tu spécifie la version de la méthode qui t'intéresse (l'autocomplétion ne semble pas prendre en compte les arguments).
Mais non, voyons. Pour faire une invocation il faut dessiner une croix à 5 branches sur le sol, et prononcer le nom de l'entité à invoquer. Techniquement la croix n'est pas strictement nécessaire, c'est un symbole d'ordre servant à emprisonner l'entité pour éviter qu'elle ne démembre l'invocateur avant de le manger.
Je ne dis pas que mon exemple est utile (j'ai pas été très inspiré), je dis juste que c'est un des concepts existant en programmation fonctionnelle que Swift te permet d'utiliser, en utilisant le Currying.
(D'ailleurs tu m'aurais demandé un exemple d'utilisation de performSelector en ObjC je crois que j'aurais pas été beaucoup plus inspiré non plus)
Si tu as fait un peu mumuse avec le Runtime d'Objective-C, tu sais déjà certainement qu'en Objective-C, les classes sont des instances de méta-classes, et que les "méthodes de classe" d'une classe ne sont en fait que des méthodes d'instances de la méta-classe. Bah là c'est un peu pareil. Les méthodes d'instance d'une classe Swift ne sont que des méthodes de classe qui prennent une instance en paramètre (et retourne une méthode à appliquer pour avoir le résultat sur ladite instance).
Après je ne suis pas assez à l'aise avec le Functional Programming et ses bonnes pratiques pour savoir te dire quand c'est utile et quand c'est + conseillé, en FP, d'utiliser ce genre de chose (méthode fonctionnelle sur une instance, type "fonctor" ou "applicateur", plutôt que de passer par de l'itératif ou autre), mais bon, tout ce que je peux te dire c'est que les faits sont là , le concept existe en FP et en Swift, c'est un fait.
Merci pour l'exemple. Je vois bien l'idée derrière, comme je dis à mes élèves, c'est du pointeur de fonction amélioré.
Par contre j'ai un soucis dans ce que m'auto complète Xcode si c'est vraiment lié à ça, c'est que ça ne semble pas spécialement intelligent ni malléable dans le sens où je ne capte toujours pas à quel moment tu spécifie la version de la méthode que tu souhaite utilisé.
Si je reprend l'exemple des NSNotifications nous avons :
Or lorsque l'on utilise le currying avec Swift, il n'affiche que :
Du coup je ne comprends pas à quel moment on est capable de lui dire quel est réellement la méthode que je cherche.
Car "postNotificationName" n'existe pas du tout en réalité. C'est soit postNotificationName:object:, soit postNotificationName:object:userInfo:
Que ce soit du Swift ou de l'ObjC, il y a besoin du nom de méthode complet pour savoir quel implémentation utiliser.
La détection ne peu se faire au nombre ni au type d'arguments mais bien au nom complet de la méthode.
Tous les exemples de currying que j'ai vu ne semblent utiliser qu'un seul argument.
Du coup je comprends pas franchement le cas d'usage si on limite ça à un seul argument.
Est une méthode (de classe) qui, une fois que tu lui as passé une instance de NSNotificationCenter, te retourne une méthode (équivalent de la méthode d'instance du NSNotificationCenter en question) prenant une NSNotification en paramètre, et l'envoie. C'est donc la version currified de la méthode d'instance suivante :
Donc il n'y a aucun souci là dessus, cette méthode qu'il te propose est valide, et ne correspond à aucune des 2 méthodes que tu as cité, mais à une 3ème dont tu avais sans doute oublié l'existence, qui est postNotification() tout court.
Si tu veux utiliser une des 2 méthodes que tu as cité, les 2 méthodes s'appellent "postNotificationName()" (et pas juste "postNotification()"). Et ces 2 méthodes se différencient juste par la liste de leurs arguments. Et chez moi elles sont bien proposées lors de l'auto-complétion sans soucis (Xcode 6.3.1), donc tout fonctionne comme attendu :
Relis le nom des méthodes. J'espère que postNotificationName ne renvois pas sur postNotification sinon on a un gros soucis ^^
Tu es en train de me dire que pour savoir quel méthode d'instance retourner ici
il va, à la compilation, essayer de deviner (dans l'intégralité du code disponible et des potentiels bundle qui ne sont pas encore écris) de quel méthode je parle ?
On marche sur la tête là non ?
C'est bien ce que j'ai écrit plus haut et ce que ma capture d'écran confirme.
Au contraire c'est tout ce qu'il y a de plus logique et c'est le principe du backtracking. J'aurais peut-être pas dû employer le terme "deviner" mais plutôt "déduire".
Et on est loin de marcher sur la tête, bien au contraire. C'est le principe même du typage implicite (et ça, ça n'a rien à voir avec le currying et avec le fait que les méthodes d'instance sont des méthodes de classe prenant l'instance en paramètre). C'est le même principe qui fait que quand tu appelles une fonction surchargée, Swift sait déduire quelle version de la fonction il doit appeler en déduisant via le type des paramètres (et via du backtracking si le type des paramètres n'est pas lui-même implicite).
D'ailleurs, j'espère que ça ça ne te surprend pas non plus, c'est un peu la base des langages de programmation moderne d'avoir un compilateur suffisamment intelligent pour déduire les surcharges à utiliser selon le contexte...
Si tu explique cela à une classe, tu les perd à "typé" pour info ;-)
On doit pas lire le même forum :
Quand à ce point, c'est l'aberration moderne que je critique depuis le début sur Swift.
La résolution statique est une connerie pure et dure. On avait un monde d'avance avec la résolution dynamique et l'ouverture que cela permet, et on est entrain de le perdre.
Mais du coup j'ai ma réponse. Cette anomalie du langage est à classer dans les conneries qui font croire que le langage est mieux alors que l'avantage présenté est carrément minoritaire par rapport aux inconvénients qu'il apporte.
Et j'ai toujours j'ai du mal à comprendre pourquoi tu parles d'anomalie du langage. Le langage a été pensé pour être un langage type-safe, donc c'est normal qu'il offre ce genre de fonctionnalités, qui sont entre autres sa force, permettant d'assurer le typage de bout en bout et d'avoir des choses comme des Array typés (generics) permettant entre autres au passage de ne pas perdre tout l'avantage de l'inférence du type des variables et des fonctions (fini les déclarations imbattables de variables de type block grace à l'inférence de type par exemple, qui n'est possible que grace à ce genre de chose comme le backtracking).
Après, si t'aimes pas et veut jouer ton puriste "je préfère avoir la main sur tout et pouvoir faire n'importe quoi si ça me chante y compris appeler des méthodes sur des objets qui n'y répondent possiblement pas sans que le compilateur me gueule dessus car je préfère que ça crash au runtime", bah rien ne t'interdit d'utiliser un autre langage, genre rester à l'Objective-C ou faire de l'Objective-C++. Ou encore d'utiliser les possibilités dynamiques de Swift " même si elles ne sont pas mises en avant car Swift n'a pas pour vocation d'inviter à ça préférant le type-safety, le dynamic runtime et les possibilités de message forwarding d'ObjC sont toujours disponibles en Swift (genre "myObject.performSelector("someMethod", withObject: foo)") si ça t'amuse et que tu tiens tant que ça.
Mais Swift a été pensé pour être type-safe " contrairement à ObjC où on pouvait faire n'importe quoi et finir par écrire du code qui ne plantait qu'au runtime sans que le compilateur ne nous prévienne avant qu'il y avait une incohérence dans notre code " donc dans ce cadre, il répond parfaitement à ce pour quoi il a été pensé. Si t'aimes pas c'est ton droit, mais chaque langage a son rôle et est prévu pour être utilisé en tant que tel.
On pourrait aussi dire que le C c'est nul car ça ne permet pas de faire de l'objet, alors que toi tu dirais c'est bien car tu as le contrôle sur tout, y compris les pointeurs et la possibilité de manipuler la mémoire au plus bas niveau, tandis que d'autres cherchent un langage de plus haut niveau pour éviter de faire n'importe quoi avec la mémoire, chacun utilise le langage qui lui correspond le mieux (et encore, en Swift rien ne t'empêche de faire du dynamic message forwarding, de l'indirection, ou même manipuler la mémoire directement via les UnsafeMutablePointer<T>, etc... donc tu as toute latitude de faire tout ça quand même, donc je vois mal en quoicela te limite à la résolution statique et en quoi tu aurais perdu tout cela, c'est encore tout à fait possible)
Tu peux faire de l'objet en C ^^
Et sinon je critique Swift car je te rappel que je viens du dev OS X à la base.
Que sur OS X on a toujours pris l'habitude de faire des framework et des système de plugin. Et que ce qui est clairement monnaie courante sur OS X est une plaie en Swift : la résolution dynamique de méthode.
Tout OS X fonctionne avec des plugins. Ouvre n'importe quelle application un peu grosse et tu verra que c'est prévu en plugin.
Analyse n'importe quelle application un peu grosse et tu verra que ça utilise la résolution dynamique de méthode à outrance.
Analyse n'importe quelle application avec un look sympa sur OS X et tu verra que tu as besoin de la résolution dynamique.
Analyse n'importe quelle application touchant au Finder sur OS X et tu verra que tu as besoin de la résolution dynamique.
Même sur mes applications simple comme ma suite Admin Tools j'utilise de la résolution dynamique et des plugins pour être le plus malléable possible à l'avenir (et ça m'a déjà servis).
Alors certes, sur des petites applications comme iOS, tu t'en fou, c'est des jouets. Quand tu es sur des applications qui te font sérieusement regretter le temps où Xcode pouvait faire de la compilation distribué et du hot fixe (des truc perdu lors du passage de gcc à llvm), bah tu pleure en voyant Swift.
C'est pas question de faire le crack en voulant tout contrôler.
C'est question d'arrêter les conneries d'environnement hyper contrôlé qui n'est pas gênant sur un gadget comme iOS quand il est question d'OS X, histoire de conserver un écosystème riche.
C'est justement exprès que j'ai pris cet exemple là (et tu es tombé dedans les pieds joints, merci ^^)
Oui et alors ? Tu peux toujours le faire...
Utiliser Swift n'empêche pas de faire des frameworks dynamiques, et chargés au runtime. Je ne comprend pas trop ce qui te fait avoir ces oeillères et être si fermé à dire que c'est pas possible, alors que j'ai déjà expliqué plus haut que rien ne t'empêchait avec Swift de faire du dispatch dynamique (sans pour autant compliquer spécialement les choses).
Que tu te bornes à ne pas aimer Swift, c'est ton droit. Mais que tu t'obstines à dire qu'il ne permet pas de faire des architectures en plugin et ce genre de choses alors qu'il peut, c'est un peu dommage de se limiter à ça.
Objective-C n'a pas été pensé pour qu'on utilise "performSelector:withObject:" partout dans notre code, personne ne va utiliser performSelector: partout là où il peut appeler directement la méthode.
Bah Swift c'est un peu pareil, tu vas pas t'embêter à faire de la résolution dynamique si t'en n'as pas besoin alors que la résolution statique, bien plus efficace (et plus rapide car ne nécessitant pas d'indirection, encore + si tu actives des options comme le mode "Whole Module Optimization"), est disponible. Mais ça veut pas dire que tu ne peux pas faire de la résolution dynamique et du dynamic dispatch en Swift, loin de là , tout comme ce n'est pas parce que tout le monde écrit plutôt "[myString length]" en ObjC que tu ne peux pas écrire "[myString performSelector:@selector(length) withObject:nil]" si ça t'amuse.
Et puis les méthodes comme NSBundle(...).loadNibNamed(_,owner:options:) ou même NSBundle(...).load() continuent d'exister et d'être accessibles en Swift, et les plugins peuvent tout à fait continuer d'être écrits en Swift (du moment que tu prévois les protocoles qui vont bien permettant de te mettre d'accord sur un contrat d'interface, comme on le fait quand on fait des plugins en ObjC, tu as même un contrôle sur le typage à la compilation)... et c'est pas prêt de changer, car comme tu le dis, c'est la base de beaucoup d'architectures OSX (mais aussi iOS et au niveau du chargement de l'UI) donc bon...
OSX, un écosystème riche ? C'est un univers d'une pauvreté affligeante comparé à la richesse et la diversité de l'écosystème Windows. Les applications sont plus jolies, plus fiables, et plus ergonomiques, mais tellement moins nombreuses. Rien que dans le domaine des jeux vidéo c'est la catastrophe absolue. Ce n'est pas pour rien que beaucoup de gens emploient Boot Camp ou des systèmes de virtualisation pour utiliser des logiciels Windows sur Mac.
Je trouve amusant de te voir expliquer que l'univers OSX est riche par rapport aux applications jouets du gadget iOS, le seul écosystème logiciel réussi d'Apple, qui fait baver d'envie Microsoft et consorts.
Je comprend que les applications iOS ne soient pas ta tasse de thé, toi qui est un homme du système, des technologies et des applications professionnelles lourdes. Mais cela ne ne donne pas le droit de qualifier l'écosystème iOS de noms d'oiseaux, surtout que son nombre d'utilisateurs et de son chiffre d'affaire est infiniment supérieur à la sphère OSX.
iOS est un marché de masse, OSX un secteur de niche.
Ce n'est pas parce qu'un langage permet de réaliser le premier projet qu'il convient au second, et ce dont doute yoann est justement que Swift ait les épaules assez solides pour ce genre de gros développement. C'est une question qui me parait tout à fait légitime.
Dis de manière beaucoup plus juste, iOS est un marché de consommation là où OS X est un marché de production. La réelle différence est là .
Tu ne produit pas sur iPad, tu consomme du contenu. De fait les applications sont vachement plus light, même si elles sont potentiellement plus rentable.
Rassure toi, on n'utilise pas des performSelector pour du dynamique mais des protocoles.
Mais dans ce que tu écris tu oubli le cas non négligeable sur OS X de la modification de ce qui n'est pas exposé.
Le dynamique sers à ça. À aller ajouter ton plugin Antidote dans Mail.app qui n'expose pas ses informations par exemple.
Je ne suis pas foncièrement contre Swift. C'est rigolo pour faire du dev formel. ça a du sens. Mais c'est très loin d'être un langage fait pour la production. Il y a beaucoup trop de contraintes dessus pour que ce soit tout simplement rentable.
Quand je lis un cours de Swift j'ai l'impression d'entendre parler un prof de faculté qui n'a jamais fait d'entreprise de sa vie.
Faire du formel quand on fait le programme de gestion de la ligne 14 (qui est toujours en version 1.0 depuis sa mise en exploitation) c'est carrément normal. Et dans ce genre de situation, Swift est une aide.
Mais il faut rester terre à terre et se dire que la plupart des projets n'ont pas les moyens d'assumer l'overhead associé. Or Swift l'imposte et Apple semble vouloir imposer Swift.
Que ce soit sur la rentabilité, la maturité ou la solidité de Swift face aux projets complexe, j'ai de très forts doutes.
Et chaque fois que je pose une question sur Swift, ça ne fait que confirmer mes doutes.
Quoi ? ! Je viens de travailler sur une appli iPad qui ne fait que produire les fiches de calcul et les rapports pour les pilotes d'avions privés.
Mais bon j'ai l'impression de me répéter et que malgré cela tu te cantonnes à ta vision limitée aux bouquins permettant d'apprendre les bases de Swift, qui évidemment ne rentrent pas dans ce genre de considérations avancées pour un bouquin qui se veut faire apprendre les bases et les cas d'usage les plus courants en Swift.
Quand j'ai appris Objective-C et commencé la programmation sous OSX, je n'ai pas commencé par apprendre et découvrir [NSBundle load], DYLD_INSERT_LIBRARIES, l'injection dynamique, le dynamic loader et les choses comme ça, et heureusement sinon j'aurai sans doute été perdu. Les bouquins qui te présentent Swift c'est pareil, ils abordent l'essentiel pour qui veut se mettre à Swift alors qu'il n'a pas non plus un niveau d'emblée pour faire comme premiers programmes des applis full-dynamic. Ca ne veut pas dire que c'est pas possible (attends 2s, que je copie-colle cette phrase, je commence à en avoir marre de la réécrire à chaque fois). Tu dis toi-même qu'en tant que prof, si tu commences à parler de ça à tes élèves tu les perds tout de suite, donc je comprends encore moins que tu penses que les bouquins qui font apprendre Swift, même ceux qui ne sont pas pour les tout débutants, ne mentionnent pas ça directement. Pourtant si tu cherches un peu, sur la toile, sur des blogs de gens comme Samuel D.Marshall ou Mike Ash ou autre, ou que tu regardes un peu les possibilités de Swift au niveau du runtime et du chargement ou injection dynamique de bundle, tu t'apercevras que c'est possible. C'est juste pas le truc que tout le monde fait tous les jours, car tout le monde ne fait pas une application bureautique OSX super chiadée avec des plugins partout tous les jours (même en Objective-C, d'ailleurs), donc c'est loin d'être la première chose que tu apprends en Swift (comme en ObjC).