Découverte syntaxe simplifiée NSArray

Salut,

Ce matin, je découvre qu'on peut définir et initialiser un tableau comme ça :



NSArray * monTableau=@[obj1,obj2];



Incroyable non ?!

Un truc de dingues image/cool.gif' class='bbc_emoticon' alt='8--)' />

Réponses

  • LeChatNoirLeChatNoir Membre, Modérateur
    Roooooo, et pour un dictionnaire !



    NSDictionary * monDict={@maClé1:maValeur1,@maClé2:maValeur2};



    image/thumbsup.gif' class='bbc_emoticon' alt='' /> image/apple.gif' class='bbc_emoticon' alt='' />
  • christopheLchristopheL Membre
    août 2012 modifié #3
    NSString *monTexte = @blabla;



    image/wink.png' class='bbc_emoticon' alt=';)' />
  • Cette nouvelle syntaxe ne fonctionne que pour le SDK MacOSX pour l'instant.

    Dommage, ...
  • Heureusement qu'on en a déjà  parle image/biggrin.png' class='bbc_emoticon' alt=':D' /> http://forum.cocoacafe.fr/topic/8585-literal-syntax-for-nsarray-nsdictionary-nsnumber/
  • AliGatorAliGator Membre, Modérateur
    Bien sur que non ça fonctionne pour iOS aussi c'est dans le nouveau compilateur LLVM du dernier Xcode4.

    Et oui on en a déjà  parlé ^^



    Il n'y a qu'un truc qui Dépend du SDK pour fonctionner, c'est l'accès indexé monArray[5] et monDico[@key] et encore qu'il suffit de définir les méthodes objectAtIndexSubscript et objectForKeySubscript correspondantes dans le cas où on utilise un SDK qui ne les définit pas encore (iOS5 par exemple) pour que ça fonctionne.



    Tout est détaillé dans les vidéos de la WWDC... et dans les autres sujets du forum où on en parle ;-)
  • J'ai bien vu les autres sujets du forum, mais comme je ne suis pas tout à  fait juriste je continue à  penser que dans Xcode 4.4.1 cette caractéristique n'est disponible que pour le SDK OSX (c'est ce qui est écrit dans la Release Note).

    Je préfère garder pour moi les caractéristiques de Xcode 4.5 et des SDK associés. LLVM n'est pas sous NDA mais par incompétence juridique (j'avoue) je considère que le fait que Xcode 4.5 utilise telle version de LLVM est sous NDA.
  • AliGatorAliGator Membre, Modérateur
    août 2012 modifié #8
    Je n'ai que XCode 4.4.1, pas Xcode 4.5 pour ma part



    Et sans parler de juriste ou de NDA, là  n'est pas la question :
    1. Ce sont des nouveautés du compilateur LLVM, et non de Xcode 4.4 à  proprement parler, même si ce nouveau compilateur LLVM étant intégré à  Xcode 4.4 on peut parfois faire la confusion par abus de langage.
    2. D'ailleurs tout ceci est décrit dans la doc officielle et sur le site de Clang-LLVM : http://clang.llvm.or...eCLiterals.html donc ça n'a rien à  voir avec un quelconque NDA Apple
    3. Puisque ce sont des fonctionnalités introduites par le compilateur, elles ne dépendent pas du SDK. Cette syntaxe est du sucre syntaxique, qui est traduit par le compilateur par les lignes équivalentes (ça aussi c'est expliqué dans les vidéos de la WWDC si ça t'intéresse). Cela ne dépend donc pas de OSX ou iOS.


    Par exemple pour les syntaxes de construction de tableau @[...] et de dictionnaire @{key:value, ...} (extrait de la doc LLVM) :
    Array literal expressions expand to calls to +[NSArray arrayWithObjects:count:] [...]. Dictionary literals are similarly created with +[NSDictionary dictionaryWithObjects:forKeys:count:][font=Lucida Grande, Lucida Sans Unicode, Arial, Verdana, Helvetica, sans-serif]
    Donc c'est exactement comme si tu tapais les lignes équivalentes dans ton code. Un peu comme un #define qui est remplacé par sa valeur à  la précompilation, si tu veux. C'est comme si tu écrivais :
    #define makeArray(...) [NSArray arrayWithObjects:__VA_ARGS__, ## nil][/size][/font]<br />
    NSArray* tab = makeArray(item1, item2, item3);
    
    Sauf que maintenant pas besoin de déclarer une macro pour ça, tu peux directement écrire :
    NSArray* tab2 = @[ item1, item2, item3 ];
    




    D'ailleurs, comme pour toute fonctionnalité propre au compilateur LLVM, on peut utiliser __has_feature(...) pour tester si le compilateur supporte ces extensions de syntaxe. Le SDK utilisé n'y changera rien, c'est une extension du compilateur pas du framework.



    Les seules choses qui dépendent du SDK, c'est le "Object Subscripting", puisqu'utiliser la syntaxe myArray[4] va être transformé par le compilateur en [myArray objectAtIndexedSubscript:4] (voir le paragraphe "subscripting methods" de la doc LLVM citée plus haut) encore faut-il que ladite méthode existe sur l'objet myArray. Or ces méthodes ne sont déclarées dans le SDK que dans les dernières versions.

    Mais bon rien ne t'empêche de les déclarer toi-même pour que ça marche même dans des versions plus anciennes (c'est ce que je fais, ça marche très bien). D'ailleurs tu peux tout à  fait utiliser cette syntaxe sur d'autres types d'objets que des NSArrays, par exemple créer une classe perso MaClasse qui supporte le subscripting, il suffit pour cela qu'elle implémente la méthode objectAtIndexedSubscript :
    The advantage of this design is flexibility: class designers are free to introduce subscripting by declaring methods or by adopting protocols. Moreover, because the method names are selected by the type of the subscript, an object can be subscripted using both array and dictionary styles.
    Donc tout comme tu peux déclarer ces méthodes sur n'importe quelle classe pour lui ajouter le support de ce sucre syntaxique, tu peux les déclarer toi-même sur NSArray et NSDictionary si tu utilises un SDK plus ancien que le dernier et qui ne les déclare pas déjà  pour toi.



    Mieux encore, en fait il faut savoir que la librairie de Runtime ARC ajoute l'implémentation de ces méthodes à  NSArray et NSDictionary au runtime, donc en fait il suffit juste de déclarer les prototypes de ces méthodes pour NSArray et NSDictionary, pas besoin de déclarer leur implémentation la lib en question les ajoute pour toi !





    Bref, et comme l'ont expliqué les gars de chez Apple à  la WWDC, ceci étant des fonctionnalités du compilateur (sucre syntaxique du langage) et non des nouveautés du SDK, cela marchera sur toute version de iOS et OSX. Il faut juste compiler avec la dernière version du compilateur, quel que soit ton SDK utilisé. Et tout ceci n'est pas du tout sous NDA puisque dépend de Clang-LLVM, projet OpenSource dont toute la doc est disponible librement.
  • LeChatNoirLeChatNoir Membre, Modérateur
    Désolé de la "redite" les gars... J'ai juste 6 mois de retard. Normal quoi image/rolleyes.gif' class='bbc_emoticon' alt='::)' />
  • Lu dans le descriptif de Xcode 4.4 sur l'AppStore : Objective-C adds literal syntax for numbers, arrays, dictionaries, and expressions when developing for OS X.

    En fait c'est une très mauvaise habitude de lire la doc image/evil.gif' class='bbc_emoticon' alt='>:D' />


    Et tout ceci n'est pas du tout sous NDA puisque dépend de Clang-LLVM, projet OpenSource dont toute la doc est disponible librement


    Je comprends qu'il n'y a pas de NDA sur LLVM, il n'y a jamais eu de problème là -dessus. Mais je reste tout à  fait incapable de comprendre l'effet que ça peut avoir sur le NDA d'Apple.
  • AliGatorAliGator Membre, Modérateur
    Oui j'avoue je ne comprend pas pourquoi ils ont indiqué "when developing for OSX" dans les Release Notes, c'est bizarre.



    Peut-être parce que le Object Subscripting n'est pas encore dispo pour iOS (et là  je viole peut-être le NDA en disant qu'il le sera dans iOS6 ?) mais que depuis OSX.7... Mais bon toutes les fonctionnalités autour des Object Literals (créer des NSArrays avec @[...], des NSDictionary avec @{...}, des NSNumber avec @x et des boxed expressions avec @(...) en particulier) sont disponibles, elles, et rien que ça c'est super pratique et disponible à  partir du moment où tu utilises le nouveau compilateur LLVM.



    Pour ce qui est du NDA, de toute façon Xcode 4.4 est sorti et n'est plus sous NDA il me semble, contrairement à  Xcode 4.5 ou iOS6 où là  ça pourrait être discutable de parler de nouveautés par encore publiques. Mais tout ce qui est propre à  LLVM, que tu peux télécharger indépendamment de Xcode, n'y est pas soumis, puisque c'est un produit indépendant. Certes, un produit qu'Apple utilise, mais que d'autres utilisent aussi et que tu peux récupérer légalement gratuitement, extérieurement à  Xcode ou à  tout contrat/License Agreement avec Apple (même qqun non inscrit à  un quelconque programme de dev Apple ou n'ayant accepté de contrat de license d'Apple ou quoi peut utiliser LLVM) sans que ce soit soumis donc à  un NDA d'Apple.
  • J'ai déclaré les prototypes des méthodes à  ajouter pour utiliser la notation script (dans des catégories de NSArray et NSDictionary), mes tests unitaires sont OK, ça a l'air de marcher.

    Mais j'ai un warning (implémentation incomplète) c'est normal et pas grave, mais j'aimerai bien pouvoir dire au compilo qu'il me laisse tranquille avec ce warning pour ce cas précis (oui je suis un maniaque du 0-warning, sauf ceux que je rajoute moi-même avec #warning). Y'aurait pas une espèce de @dynamic qui marche avec les méthodes ?
  • AliGatorAliGator Membre, Modérateur
    août 2012 modifié #13
    C'est bizarre, moi je n'ai aucun warning une fois les méthodes en question ajoutées. Tu as modifié les réglages par défaut du compilateur pour afficher plus de warnings que moi ?



    En tout cas voilà  ce que j'ai mis (dans un fichier ObjcLiterals.h, que je #import dans mon fichier PCH pour que ces méthodes soient accessibles partout et pouvoir utiliser les syntaxes associées partout dans mon code) :
    #if __has_feature(objc_subscripting)<br />
    #if (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) &amp;&amp; __MAC_OS_X_VERSION_MAX_ALLOWED &lt; 1070)	 /* Define this on OSX only if prior to 10.7 */ \<br />
    ||  (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) &amp;&amp; __IPHONE_OS_VERSION_MAX_ALLOWED &lt; 60000) /* Define this on iOS only if prior to 6.0 */<br />
    <br />
    @interface NSArray(ObjcLiterals)<br />
    -(id)objectAtIndexedSubscript:(NSUInteger)index;<br />
    @end<br />
    @interface NSMutableArray(ObjcLiterals)<br />
    -(void)setObject:(id)anObject atIndexedSubscript:(NSUInteger)index;<br />
    @end<br />
    @interface NSDictionary(ObjcLiterals)<br />
    -(id)objectForKeyedSubscript:(id)aKey;<br />
    @end<br />
    @interface NSMutableDictionary(ObjcLiterals)<br />
    -(void)setObject:(id)anObject forKeyedSubscript:(id&lt;NSCopying&gt;)aKey;<br />
    @end<br />
    <br />
    #endif<br />
    #endif<br />
    




    PS : Je ne peux que valider ton approche "0-warning", et dans cette idée, je te conseille d'utiliser plutôt l'astuce que je décris dans cet autre sujet que je viens d'ouvrir pour générer tes messages de compilation. Perso je peux plus m'en passer image/smile.png' class='bbc_emoticon' alt=':)' />
  • J'ai compris mon warning. J'avais fait une économie de catégorie en glissant les deux prototypes dans l'interface d'une catégorie existante ; bien sûr ça ne plaisait pas à  Xcode quand il compilait l'implémentation de ladite catégorie.



    PS : Bonne idée très propre cette histoire de _pragma
Connectez-vous ou Inscrivez-vous pour répondre.