[Astuce] implémenter un protocole par autocomplétion

AliGatorAliGator Membre, Modérateur
septembre 2009 modifié dans Objective-C, Swift, C, C++ #1
Hello les gens,

Je recherche une astuce (je me demande si elle existe pas déjà , et sinon comment on pourrait faire pour créer un plugin ou un AppleScript ou une TextMacro pour ça) pour rapidement implémenter un protocole dans mon code.

Je m'explique : à  chaque fois qu'on développe une classe et que l'on veut qu'elle réponde à  un protocole (ce qui est d'ailleurs encore plus fréquent avec l'iPhone SDK où par exemple tous les delegates des classes CocoaTouch sont de type "id<protocol>"), il faut aller rechercher dans la doc la signature des méthodes du protocole et les copier/coller dans notre code pour les implémenter. Ou les taper à  la main et jouer de l'autocomplétion, encore faut-il se rappeler de leur nom même si certainesont un nom explicite, il faut éviter d'en oublier...


Jusque-là  le meilleur moyen que j'ai trouvé pour coller rapidement toutes les méthodes à  implémenter pour répondre à  un protocole donné, c'est de taper (ou trouver qqpart dans mon code) le nom du protocole à  implémenter, de faire pomme-clic sur ce nom pour arriver à  sa définition dans le header Apple (ou pas) correspondant, et copier-coller toutes les méthodes dans mon code... puis enlever les lignes en surplus (commentaires, mention "@optional";, ...), et enfin remplacer tous les ";" par des "{" et "}" à  la main...

Mais je me dis que si on pouvais automatiser ça, ça serait quand même vachement sympa ! Genre on tape "UITableViewDelegate"+<esc> dans le code et hop ça nous propose d'insérer automatiquement dans notre ".m" toutes les méthodes de ce protocole, prêtes à  être implémentées... quitte à  ce que ça indique en commentaire celles qui sont optionnelles et qu'on les jarte à  la main si on n'en a pas besoin... ou mieux que ça nous propose d'insérer automatiquement soit que les méthodes obligatoires du protocole, soit toutes les méthodes, optionnelles comprises...


Des idées pour mettre cette astuce en place ?
Bien sûr y'a une solution envisageable, ça serait de rentrer tous les protocoles connus dans un fichier de TextMacros, j'ai bien pensé le faire mais (1) un peu rébarbatif à  rentrer, faudrait les rentrer tous sans en oublier un seul et (2) ça n'est pas évolutif avec la doc, l'idéal serait d'aller chercher les infos directement en parsant les headers, non ?

Réponses

  • Philippe49Philippe49 Membre
    mars 2009 modifié #2
    dans 1237729072:

    il faut aller rechercher dans la doc la signature des méthodes du protocole et les copier/coller dans notre code pour les implémenter.


    Un raccourci est d'utiliser le Research Assistant : tu écris UITableViewDelegate n'importe où, et le Research Assistant te mets le lieu où se trouve le .h définissant le protocole. Tu cliques sur ce .h et tu te retrouves exactement sur la définition dudit protocole. Il ne reste plus qu'à  copier-coller ...

    Automatiser cela par un script ?

    [EDIT] Hum ... pas si simple, cela marche, mais moins bien pour le NSOutlineViewDatasource protocole
  • AliGatorAliGator Membre, Modérateur
    22:28 modifié #3
    dans 1237734554:
    Un raccourci est d'utiliser le Research Assistant : tu écris UITableViewDelegate n'importe où, et le Research Assistant te mets le lieu où se trouve le .h définissant le protocole. Tu cliques sur ce .h et tu te retrouves exactement sur la définition dudit protocole. Il ne reste plus qu'à  copier-coller ...
    C'est ce que je fais avec pomme-clic sur le nom du protocole (au lieu d'utiliser le Research Assistant) jusqu'à  présent...
    dans 1237734554:
    Automatiser cela par un script ?
    Ben c'est bien l'idée qui m'intéresse...
  • AliGatorAliGator Membre, Modérateur
    août 2009 modifié #4
    Re tout le monde,

    Après avoir galéré pas mal, j'ai fini par aboutir à  un script sed pour parser tous les .h d'un répertoire, rechercher les blocs @protocol...@end et les transformer en TextMacros... J'en ai ch*é avec quelques cas particuliers, mais j'ai fini par y arriver !

    Installation :
    • décompressez le ZIP (si Safari ne l'a pas fait pour vous) où vous voulez sur votre disque por obtenir le dossier "protocols2textmacro"
    • lancez le terminal et exécutez le script "protocols2textmacro.sh", en passant en premier paramètre le chemin vers le dossier à  scanner (par exemple "[tt]~/Desktop/protocols2textmacro.sh /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.2.1.sdk/System/Library/Frameworks[/tt]") ; si vous ne spécifiez aucun argument cela scannera le répertoire courant.
    • Il va vous demander de confirmer le dossier à  parser, vous demander le nom du fichier xctxtmacro à  créer (validez pour accepter le nom par défaut), et le nom du menu à  créer dans Xcode (laissez vide et validez pour garde celui par défaut)

    Cela va alors vous créer un fichier [tt]Protocols.xctxtmacro[/tt] (ou le nom que vous avez demandé le cas échéant) dans [tt]/Users/olivier/Library/Application Support/Developer/Shared/Xcode/Specifications[/tt]. Relancez Xcode et vous devriez avoir un menu "Protocols implementation" (ou le nom que vous lui avez demandé le cas échéant)


    Utilisation
    Comme j'ai, en tout logique, associé comme "CompletionPrefix" pour chaque protocole le nom dudit protocole, il vous suffit, une fois le fichier de TextMacros créé, de lancer Xcode et vous placer dans un de vos fichier .m, entre un bloc @implementation et @end là  où insérer les méthodes, puis taper le nom d'un protocole et demander l'autocomplétion.
    Ainsi, si vous tapez "UITableViewDe"+<esc> cela va vous proposer "UITableViewDelegate implementation" et si vous validez, cela va insérer toutes les méthodes @required du protocole ainsi que les méthodes @optional entourées de /*...*/ qu'il vous suffit de décommenter si vous souhaitez les implémenter.

    Phase de beta-tests
    Perso je n'ai testé la création de ces TextMacros par mon script qu'avec le Framework iPhoneSimulator 2.2.1 et ça a l'air de marcher... mais j'ai pas vérifié qu'il n'avait pas oublié de @protocol ni qu'il avait correctement parsé les fichiers.
    Merci si vous testez ce script et utilisez les TextMacros de me faire des retours pour me spécifier si tout marche bien ou s'il manque des choses, etc...
    Et puis si tout marche bien je le posterai dans "Trucs & Astuces" du site ;)


    PS : Si y'en a qui veulent des explications sur le code de mon script sed, qu'ils n'hésitent pas, maintenant je commence à  bien maà®triser du coup :P

    [EDIT] : Fichier joint supprimé, nouvelle version corrigeant des bugs dans le post suivant
  • AliGatorAliGator Membre, Modérateur
    mars 2009 modifié #5
    Nouvelle version, même principe :

    ./protocols2textmacro/protocols2textmacro.sh /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.2.1.sdk/System/Library/Frameworks/
    


    --> Vous crée le fichier de TextMacros contenant tous les @protocols listés dans le Framework (ici iPhone221 mais choisissez un autre dossier selon vos désirs)
    --> Vous n'avez plus qu'à  taper dans votre code le nom du protocole puis taper la touche d'autocomplétion (<esc> chez moi) pour qu'il vous propose de vous insérer toutes les méthodes @required (+ les @opional commentées entre /*...*/) du protocole dans votre .m !

    Cette nouvelle version corrige juste des bugs dans le script sed qui faisaient que certaines méthodes étaient oubliées ou d'autres vues comme @optional au lieu de @required (ou vice-versa) si le @optional était juste après une méthode ignorée...
  • GreensourceGreensource Membre
    mars 2009 modifié #6
    Je n'ai pas de menu qui s'est créer chez moi. Idem j'ai essayer l'auto-complétion mais rien..
    Je ne sais pas trop d'où ça peut venir, ni te donner plus d'info, je vais essayer de voir.

    [edit] J'ai trouver, c'est parce que je n'avais pas de répertoire Specifications dans : [tt]/Users/olivier/Library/Application Support/Developer/Shared/Xcode/[/tt]
  • AliGatorAliGator Membre, Modérateur
    mars 2009 modifié #7
    dans 1237883633:

    Je n'ai pas de menu qui s'est créer chez moi. Idem j'ai essayer l'auto-complétion mais rien..
    Je ne sais pas trop d'où ça peut venir, ni te donner plus d'info, je vais essayer de voir.

    [edit] J'ai trouver, c'est parce que je n'avais pas de répertoire Specifications dans : [tt]/Users/olivier/Library/Application Support/Developer/Shared/Xcode/[/tt]
    Ah oui tiens j'ai pas pensé à  ce cas de figure. Bon ceci dit il doit sans doute te mettre "-bash: /Users/olivier/Library/.....: No such file or directory" non ? Ce qui a dû te mettre sur la piste ?
    Bon je modifierai mon script pour qu'il crée le répertoire si inexistant, en plus c'est pas méchant. Bonne remarque.


    Sinon rassure-moi, tu t'appelles bien Olivier comme moi ? Donc ce n'est qu'un hasard si ton répertoire maison ($HOME) s'appelle aussi "olivier" exactement comme moi hein ? Et non pas un relicat de mon nom de répertoire maison que j'aurais laissé en dur dans le script, risquant de faire qu'il ne fonctionne pas chez ceux dont le répertoire maison aurait un autre nom ? :P


    Merci de ton test en tout cas.

    PS : J'ai modifié l'exemple dans mon post plus haut, dans le chemin du dossier de Frameworks à  parser, j'avais omis de mentionner "/Developer" donc ça n'aurait produit qqch que si on était déjà  dans /Developer...
  • GreensourceGreensource Membre
    22:28 modifié #8
    Tu peux être rassuré, si je ne m'appelle pas olivier mais Pierre, tu n'as pas non plus laissé trainé ton nom en dur. C'est juste un copié/coller du forum  :P

    Par contre je ne me rappel pas avoir eu une erreur de répertoire, c'est pour ça que je n'ai pas compris pourquoi je n'avais pas de menu. Je suis aller voir avec un cd ce qu'il y avais dedans et là  j'ai vu que le répertoire n'existait pas.
    Voilà , en tout cas merci pour ce script, si j'en ai pas encore eu l'utilité, je pressent que ça ne va pas tarder ^^
  • schlumschlum Membre
    22:28 modifié #9
    Je crois pas que tu le rassures, il espérait justement que tu t'appelles Olivier  ;D
  • AliGatorAliGator Membre, Modérateur
    22:28 modifié #10
    Nouvelle version (1.2) qui teste l'existence du répertoire avant de créer le fichier xctxtmacro, et vérifie aussi que le chemin passé en argument est un chemin valide (répertoire qui existe et dans lequel on peut aller lire)
  • AliGatorAliGator Membre, Modérateur
    septembre 2009 modifié #11
    Nouvelle version 1.5 :

    • Compatible Xcode 3.2 : rajout de la clé "OnlyAtBOL=YES" dans toutes les TextMacros (ce qui est cohérent car on n'est sensé taper le nom du protocole -- pour en insérer les modèles de méthodes -- au début d'une ligne et pas en plein milieu de toute façon.
    • L'interface ligne de commande est plus propre à  manipuler, la synthèse des données avant la création est plus lisible... Tapez "[tt]protocols2textmacro.sh -h[/tt]" pour afficher l'aide de l'utilitaire.
    • Nouveau flag "-sdk" qui permet d'indiquer une version de sdk directement plutôt qu'un path à  ralonge. Préciser ainsi "-sdk 3.1" aura le même effet que de préciser le chemin complet [tt]/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.sdk/System/Library/Frameworks/[/tt]... mais c'est quand même moins long à  taper !
    • Comme avant, pour les paramètres que vous ne précisez pas, ils vous seront demandés interactivement, en proposant une valeur par défaut. Si vous indiquez le flag "-sdk" sans aucun autre paramètre, c'est la version du SDK qui vous sera demandée interactivement (en listant les SDK détectés et proposant le dernier par défaut) au lieu de vous demander le chemin
    • Possibilité de préciser un suffixe aux TextMacros générées, ce qui s'avère très utile si vous souhaitez générer les TextMacros pour des versions de SDK différentes, pour ainsi avoir dans le menu d'autocomplétion par exemple la précision "(SDK 2.2.1)" pour la version 2.2.1 de la TextMacro, et "(SDK 3.1)" pour celle de la 3.1...
    • Les placeholders [tt]<#statements#>[/tt] générés par la TextMacro dans les templates d'implémentations des protocoles sont maintenant suffixés d'un numéro incrémental ([tt]<#statements_12#>[/tt] etc) les rendant ainsi uniques et évitant ainsi d'en modifier plusieurs à  la fois (car si l'on se place sur un placeholder et lui donne une valeur, on va changer en même temps la valeur de tous les placeholders portant le même nom)


    Voilà  je pense avoir fait le tour.

    Pour ma part j'utilise mon script en l'appelant tout simplement par "[tt]./protocols2textmacro.sh -sdk[/tt]" et comme les valeurs par défaut me vont je n'ai plus qu'à  valider (en mm temps c'est normal c'est moi qui les ai définies :))


    [EDIT]
    Désolé j'ai posté un peu vite et n'avais pas testé avec les SDK de MacOSX (seulement iPhone). La version 1.5.2 est du coup disponible dans le post suivant (j'enlève le fichier joint v1.5 de ce post pour éviter les profusions de versions).
  • AliGatorAliGator Membre, Modérateur
    septembre 2009 modifié #12
    Nouvelle version (mineure) 1.5.2 ci-dessous qui corrige :
    • le cas particulier où @protocol et @end sont sur la même ligne dans les headers parsés
      (étonnamment, cela arrive, en particulier dans le header NSMatrix.h du SDK 10.6, définissant un @protocol totalement vide pour le coup, mais sans doute en prévision de l'introduction de ce @protocol dans une future version ?)
    • le cas des caractères UTF-8 tels que "'" (guillemet courbe, parfois présent dans certains commentaires de méthodes par exemple) qui peuvent faire foirer sinon le chargement du xctxtmacro par Xcode. Le xctxtmacro est maintenant converti avec le bon encoding.


    Ces erreurs empêchaient le fichier xctxtmacro généré par le SDK de MacOSX 10.6 de se charger dans Xcode (le @protocol et @end sur la même ligne faisait foirer mon parsing sed, le mauvais encodage du texte faisait foirer le parsing du xctxtmacro par Xcode)

    • De plus, cette version voit aussi l'arrivée d'un nouveau flag "-osx" qui est le pendant du flag "-sdk" mais pour les SDKs MacOSX et non iPhone. Ainsi vous pouvez préciser "[tt]./protocols2textmacro -osx[/tt]" et cela vous demandera quelle version du SDK MacOSX vous voulez parser parmi les présents, comme "[tt]./protocols2textmacro -sdk[/tt]" vous demande la version du SDK iPhone à  parser.


    Vous pouvez donc maintenant aussi utiliser cette version du script pour parser les @protocols du SDK 10.6 !
Connectez-vous ou Inscrivez-vous pour répondre.