[Résolu] Comment sauver une chaà®ne de caractères dans une structure C avec NSData?

HerveHerve Membre
août 2013 modifié dans API AppKit #1

Bonjour,


 


Je ne trouve pas la solution au problème suivant :


Une application Cocoa sauve avec NSData une structure C qu'un plug-in Audio unit (écrit en C++) récupère. Jusqu'à  présent, il n'y avait que des float, int et boolean dans cette structure. Pas de problème, cela marche très bien.


 


J'aimerais y ajouter des chaà®nes de caractères sauvés et relus par le plug-in par la même structure C écrite sur le disque avec NSData. (le plug-in utilise quant à  lui CFDataRef ).


Je n'arrive pas à  utiliser CFString, ni à  faire marcher des tableaux de caractères du genre 



char mesNoms[32][32];

bien que ceci serait sans doute la meilleure solution en termes de compatibilité entre Cocoa et C++.


 


Bref, comment feriez-vous? Merci par avance pour votre aide.


«1

Réponses


  • NSData *data = [NSData dataWithBytes:&mesNoms length:sizeof(mesNoms)] ?

    Pas sûr sur le sizeof par contre... Ptêt' sizeof(char)*32*32...

  • mpergandmpergand Membre
    août 2013 modifié #3

    Sois plus précis, c'est quoi ton problème, un problème d'encoding ?


     


    Avec char mesNoms[32][32 tu déclares un tableau de 32 strings de 31 cars de long


    C'est bien ce que tu veux ?


     


    Montre ton code !


  • AliGatorAliGator Membre, Modérateur
    août 2013 modifié #4
    mesNoms[32][32] est un tableau de 32 pointeurs, pointant chacun vers un tableau de 32 chars.
    Mais ces 32*32 chars ne sont pas forcément dans une zone mémoire contiguë ! Tu peux avoir le premier tableau de 32 chars (la première chaà®ne de 32 caractères) à  un endroit, la seconde dans une autre zone mémoire, etc. et ton tableau mesNoms[32][32] va contenir les adresses de chacune de ces zones mémoires de 32 chars.

    Du coup tu ne peux pas copier tout d'un coup en une seule instruction.
    Je pense qu'il faut que tu boucles sur ton tableau de 32 chaà®nes, et que tu les enregistres une par une. Un truc du genre (pas testé) :
    static size_t const kNbStrings = 32;
    static size_t const kStringLen = 32; // terminateur NUL compris
    char mesNoms[kNbStrings][kStringLen];

    NSMutableData* data = [NSMutableData dataWithCapacity:kNbStrings*kStringLen*sizeof(char)];
    for(size_t i=0; i<kNbStrings; ++i) {
    [data appendBytes:mesNoms[i] length:kStringLen*sizeof(char)];
    }


  • mesNoms[32][32] est un tableau de 32 pointeurs, pointant chacun vers un tableau de 32 chars.


     




     


    Tu es sûr de toi Ali ? L'un de nous deux doit réviser son K&R.

  • HerveHerve Membre
    août 2013 modifié #6

    Merci à  tous pour ces premières réponses.


    En fait, la structure à  sauvegarder est faite elle-même de structures imbriquées.


     


    La voici sans les noms :



    struct unPoint {
    int indexCouleur;
    int position;
    };
    typedef struct unPoint unPoint;

    struct AjoutOnde{
    int numeroOnde;
    float valeursOnde[24];
    };
    typedef struct AjoutOnde AjoutOnde;

    struct UneCouleurSon {
    Float32 hueVal;
    Float32 satVal;



    //etc. Autres valeurs encore.
    }; typedef struct UneCouleurSon UneCouleurSon;

    struct LigneAU{
    int numNote;
    int nbPoints;
    //etc. Autres valeurs encore.

    unPoint lesPoints[50];
    };
    typedef struct LigneAU LigneAU;

    struct Patch {
    int typePatch; int nbCouleurs;
    int nbLignes;
    //etc. Autres valeurs encore.

    UneCouleurSon lesCouleursSon[60];
    LigneAU lesLignes[51];
    AjoutOnde ondeAjoutee[60];
    };
    typedef struct Patch Patch;


    struct ProgrammesMIDI {
    Patch lesPatchs[32];
    };
    typedef struct ProgrammesMIDI ProgrammesMIDI;


     


    J'aimerais ajouter dans la structure Programmes MIDI de préférence, sinon à  défaut dans celle "Patch" ma chaà®ne de caractères.


  • mpergandmpergand Membre
    août 2013 modifié #7


    mesNoms[32][32] est un tableau de 32 pointeurs, pointant chacun vers un tableau de 32 chars.



     


    <_<


     


    char (*str[32])[32]; 


     


     



     


    J'aimerais ajouter dans la structure Programmes MIDI de préférence, sinon à  défaut dans celle "Patch" ma chaà®ne de caractères.



     


    Si dans patch tu ajoutes char nom[32]; 


    quel est le problème ?


     


  • AliGatorAliGator Membre, Modérateur

    Tu es sûr de toi Ali ? L'un de nous deux doit réviser son K&R.

    Heu parce que, pour toi c'est quoi ?

    "char lesNoms[32][32]" pour moi c'est un char**, donc un tableau de char* : donc tu as 32 chaà®nes, chaque chaine étant un char[32] donc un tableau de 32 chars (une chaà®ne de 31 caractères + NUL terminator)

    Tu as peut-être par exemple :
    - la première chaine (char[32], tableau de 31 caractères + NUL) qui commence à  l'adresse 0x00cc0a00 (son premier caractère est en 0x00cc0a00, son 2ème caractère en 0x00cc0a01... son 31ème caractère en 0x00cc0a1f),
    - la 2ème chaà®ne commence à  l'adresse 0x00cc0b00 (ses caractères sont dans la zone mémoire qui va de 0x00cc0b00 à  0c00cc0b20, NULL compris),
    - la 3e qui commence à  l'adresse 0x00cd1a00,
    - ...
    Et ton tableau "lesNoms" est un tableau de char*, donc un tableau de pointeurs qui pointent chacun vers le premier char de chaque chaà®ne, autrement dit c'est le tableau { 0x00cc0a00, 0x00cc0b00, 0x00cd1a00, ... }.

    On a donc bien un tableau de 32 pointeurs, chacun pointant vers le premier caractère d'une chaà®ne de 32 chars (NUL inclus).
  • AliGatorAliGator Membre, Modérateur

    <_<
     
    char (*str[32])[32];

    Heu Herve a indiqué que lesNoms était défini comme "char lesNoms[32][32]", pas comme "char* str[32][32]" si j'ai bien lu, non ? Donc je maintiens, un tableau de 32 pointeurs (32 char*), chacun étant un pointeur vers un char, qui est le début d'une chaà®ne de 31 caractères.. Donc un tableau de 32 chaà®nes, quoi, mais 32 chaà®nes qui ne sont pas forcément contiguës en mémoire. Chaque chaà®ne a ses 32 chars (31 caractères + NUL) les uns derrière les autres dans sa zone mémoire, mais chacune des chaà®nes peut être à  des endroits totalement différents en mémoire, ce n'est pas forcément un bloc de 32*32 octets côtes à  côtes mais peut-être 32 zones mémoires distinctes de 32 octets chacune.

    Bon après y'a des chances quand même que ça le soit, vu que le compilateur va certainement allouer les zones l'une après l'autre, au final ça risque fort d'être continu. Mais conceptuellement pour mois d'après la définition de ce type, on ne devrais pas se baser sur l'espoir que les 1024 octets utilisés pour représenter ces 32 tableaux de 32 caractères soient contigus, si ?
  • mpergandmpergand Membre
    août 2013 modifié #10

    char str[32][32] est équivalent à  char (*str)[32]


    c'est à  dire un pointeur de 32 cars, pas 32 pointeurs de 32 cars !


     


    alors qu'avec char (*str[32])[32]; 


     


    on a bien un tableau de 32 pointeurs sur 32 cars.


     


  • AliGatorAliGator Membre, Modérateur
    Heu je pense qu'on est d'accord mais qu'on fait trop d'ellipses et qu'on n'utilise pas le bon vocabulaire.

    Par exemple, quand tu dis "un pointeur de 32 cars" ça veut rien dire. C'est soit un "pointeur vers un tableau de 32 chars" (et si c'est ça, là  oui je suis d'accord) soit "un tableau de 32 chars" (et là  je suis pas d'accord)

    - char* str c'est une chaà®ne (un pointeur vers un char, en vrai, mais on s'attend que ce soit le premier char d'une chaà®ne terminée par NUL)
    - char str[32] c'est une chaà®ne aussi, de 31 caractères + NUL (un tableau de 32 char en vrai, donc une suite de caractères, donc une chaà®ne)
    - char* str[32] j'avoue que j'hésite à  dire si c'est un tableau de 32 "char*", qui sont chacun une adresse sur le début d'une chaà®ne C (c'est donc un tableau de 32 chaà®nes, ce que je dis depuis le début, mais ces 32 chaà®nes ne sont pas forcément côte à  côte en mémoire), ou un pointeur vers un tableau de 32 char, donc un pointeur vers une chaà®ne (plus exactement un pointeur (char**) vers le pointeur (char*) indiquant l'adresse du premier caractère (char) de la chaà®ne). Mais en aucun cas c'est juste directement un tableau de 32 chars en tout cas comme tu as l'air de le dire mpergand (car ça c'est "char str[32]"). Ou alors tu n'as pas utilisé les bons termes


    Pour moi "char str[32]" c'est un peu comme "char* str" suivi de "str = malloc(32*sizeof(char))" suivi d'un "free" automatique à  la sortie du contexte. C'est un pointeur vers le premier char d'une zone mémoire contenant 32 chars les uns derrière les autres. Juste "char* str" c'est un pointeur vers un char, mais "char str[32]" implique que derrière on alloue sur le tas la place pour 32 de ces chars qui vont être les uns derrière les autres en mémoire, et notre pointeur str pointe vers le premier char de cette suite de 32 chars, str étant ainsi un tableau de 32 chars, autrement dit une chaà®ne de 31 caractères + NUL.
  • Cela fait toujours du bien de discuter de son problème avec les autres. je ne sais pas pourquoi, mais suite à  mon post, j'ai eu l'idée de faire :



    struct NomDePatch{
    char lesLettres[32];
    };
    typedef struct NomDePatch NomDePatch;

    struct ProgrammesMIDI {
    PatchDazibao lesPatchs[32];
    NomDePatch lesNomsDesPatchs[32];
    };
    typedef struct ProgrammesMIDI ProgrammesMIDI;

    Et là , plus de problème, tout marche très bien. C'est marrant comment on ne voit pas les trucs simples qui tombent sous le sens!!!


  • Si les informaticiens faisaient spontanément des choses simples, ça se saurait ..
  • mpergandmpergand Membre
    août 2013 modifié #14


    Cela fait toujours du bien de discuter de son problème avec les autres. je ne sais pas pourquoi, mais suite à  mon post, j'ai eu l'idée de faire :



    struct NomDePatch{
    char lesLettres[32];
    };
    typedef struct NomDePatch NomDePatch;

    struct ProgrammesMIDI {
    PatchDazibao lesPatchs[32];
    NomDePatch lesNomsDesPatchs[32];
    };
    typedef struct ProgrammesMIDI ProgrammesMIDI;

    Et là , plus de problème, tout marche très bien. C'est marrant comment on ne voit pas les trucs simples qui tombent sous le sens!!!




     


    Je ne comprends pas en quoi mettre le tableau de cars dans une structure résoud ton problème (d'ailleurs j'ai toujours pas compris lequel)


    Donc tu as 32 noms de patchs qui font chacun 32 cars.


    tu y accèdes par


    char* nomPatch=lesNomsDesPatchs[n].lesLettres;  // lesLettres est l'adresse du tableau de 32 cars que l'on affecte à  un pointeur


     


    si tu n'utilises pas de struct, tu déclares:


    char lesNomsDesPatchs[32][32];


    et tu y accèdes par:


    char* nomPatch=lesNomsDesPatchs[n];


     


    Pourquoi faire compliqué ...




  • Heu parce que, pour toi c'est quoi ?

     




     


    Pour moi char toto [32][32] réserve une zone de 1024 chars, char * toto [32] réserve une zone de 32 pointeurs sur des chars. Et un pointeur n'a pas la même taille qu'un char.

  • mpergandmpergand Membre
    août 2013 modifié #16


    Heu je pense qu'on est d'accord mais qu'on fait trop d'ellipses et qu'on n'utilise pas le bon vocabulaire.




     


    Non, on n'est pas d'accord :)


     


    Car un tableau ne contient pas de pointeurs quelque soit sa dimension.


     


    Si tel était le cas, alors je pourrais écrire:


    char str[2][32];


    str[1]++;


    et là  compilo pas content !


    Un tableau est seulement une adresse en mémoire, pas un pointeur.


     


    Par contre en paramètre d'une fonction je peux faire:


     


    void ff(char str[])  // ou char* str


    {


      str++;


    }


     


    ici char str[] est équivalent à  char* str,  car le paramètre est un pointeur créé dans la pile


  • AliGatorAliGator Membre, Modérateur
    Est-ce que tu peux être plus précis dans tes termes utilisés, mpergand, vu que le sujet porte justement sur les bons termes et la signification exacte de ces notations ?

    Car par exemple quand tu dis :

    Car un tableau ne contient pas de pointeurs quelque soit sa dimension.

    Je ne comprends pas trop... "char* tab[32]" n'est pas un tableau de 32 "char*", et donc un tableau de pointeurs vers des char ? "int* tab[32]" n'est pas un tableau qui contient des pointeurs vers des int ?
     
    Car par exemple quand tu dis :

    Si tel était le cas, alors je pourrais écrire:
    char str[2][32];
    str[1]++;
    et là  compilo pas content !
    Un tableau est seulement une adresse en mémoire, pas un pointeur.

    Oui, là  par contre c'est moi qui ai pris un raccourci et fait l'amalgame entre pointeur et adresse mémoire, c'est vrai. Au lieu de dire "un tableau de pointeurs vers des char" j'aurais dû dire "un tableau d'adresses mémoires", ou plus exactement "une adresse mémoire correspondant au début d'une zone mémoire de taille suffisante pour stocker à  la suite 32 adresses mémoires, chacune de ces 32 adresses mémoire étant le début d'une zone mémoire pour stocker les 31 caractères + NUL de la chaà®ne".

    En plus, avec une déclaration "[]" la zone mémoire est réservée à  la compilation, dans le tas, et donc son adresse est fixée à  la compilation et ne peut pas être changée au runtime. D'où le fait qu'on ne puisse pas faire un "++" dessus (je me demande si on ne peut pas considérer que "char str[2][32]" n'est pas plutôt équivalent à  "char *const *const" en terme de typage, dans le sens où ce sont des zones mémoires allouées sur le tas et dont on ne peut pas changer les adresses ensuite, mais bon je ne sais pas si c'est vraiment une bonne façon de voir les choses)
  • jpimbertjpimbert Membre
    août 2013 modifié #18


    Car par exemple quand tu dis :Oui, là  par contre c'est moi qui ai pris un raccourci et fait l'amalgame entre pointeur et adresse mémoire, c'est vrai. Au lieu de dire "un tableau de pointeurs vers des char" j'aurais dû dire "un tableau d'adresses mémoires", ou plus exactement "une adresse mémoire correspondant au début d'une zone mémoire de taille suffisante pour stocker à  la suite 32 adresses mémoires, chacune de ces 32 adresses mémoire étant le début d'une zone mémoire pour stocker les 31 caractères + NUL de la chaà®ne".




     


    C'est là  qu'il faut que tu révises ton K&R. char toto [32][32] ça réserve une zone mémoire de 1024 chars. Y'a pas de pointeurs ni d'adresses mémoire là -dedans.


  • Cacahouètes, popcorns, chocolats, chips ? Profitez de l'entracte. Le combat vas bientôt reprendre. Ali-le-cogueur enfile ces gants de boxe collector Amstrad.
  • AliGatorAliGator Membre, Modérateur
    Ok.

    Donc dans ce cas, toto est un char* ou un char** ? Si je dois écrire une fonction et lui passer toto en paramètre, je dois écrire "void f(char*)" et pas "void f(char**)" du coup ? Et quel est le type de "toto[5]" ?

    Et si "char toto [32][32]" est exactement la même chose que char "toto[1024]" au niveau réservation de la zone mémoire :
    - Est-ce que le compilo va gueuler si j'écris "toto[40][2]" dépassant les bornes du 32*32 ou est-ce qu'il s'en fout puisque de toutes façons il traduit ça par 40*32+2 et que ça reste <1024 ?
    - Pourquoi le code d'origine de Hervé, consistant à  créer un NSData directement à  partir de l'adresse de cette zone contiguë de 1024 chars, ne marchait pas ?
  • Tu veux que je réponde à  tes questions ou elles sont seulement rhétoriques ?


    Tu as peut-être eu le temps de tester quelques lignes de C ?


  • mpergandmpergand Membre
    août 2013 modifié #22

    Petit cours sur les tableaux du C for newbie  :lol:


     



     


    Est-ce que le compilo va gueuler si j'écris "toto[40][2]" dépassant les bornes du 32*32



     Beuh, le C ça vérifie rien, c'est "No string attached"


     


    si je déclare un tableau à  deux dimensions:


    int tab[2][10];


     


    quand je fais :


    int* tab1=tab[1];


     


    tab[1] est une adresse qui est le résultat d'un calcul par le compilo (adresse de tab+10)


     


    si je veux passer ce tableau à  une fonction, il faut que je spécifie la taille du premier tableau.



    void fonction(int tab[][10]) // ou int (*tab)[10]
    {
    int* tab1=tab[1];
    printf("ad tab1 %p\n",tab1);
    }

    // main

    int tab[2][10];
    int* tab1=tab[1];

    printf("ad tab1 %p\n",tab1);

    fonction(tab);

    // résultats:
    ad tab1 0xbfffe9a4
    ad tab1 0xbfffe9a4

  • FKDEVFKDEV Membre
    août 2013 modifié #23

    Pour s'en sortir il faut regarder quel est le type dont on va créer un tableau et savoir que toutes les cases d'un tableau sont forcément contiguës (quelque soit le nombre de dimension). 


     


     


    char tab1[32][32]; => sizeof(tab1) = 1024


    char *tab2[32];    => sizeof(tab2) = 256  = 32*8    (sur un mac 64 bits)


    char *tab3[32][32];=> sizeof(tab3) = 8192 = 32*32*8 (sur un mac 64 bits)


     


     


    La version verbose :


    1/ char tab[32][32] crée un tableau d'éléments de type char. Et il y en a 32*32.


     


    Cela donne bien une zone mémoire de 1024 char consécutif. La variable "tab" va contenir l'adresse de cette zone mémoire.


    tab:[ adresse (disons 64 bits)  ]---> [ ] [ ] [ ] ... (32 cases de 1 octet)


                                          [ ] [ ] [ ]


                                           ... (32 lignes)


     


    En mémoire, les lignes sont consécutives pour faciliter le travail du compilateur  :


    tab:[   ]---> [ ] [ ] ... 1024 cases.


     


     


    2/ char *tab[32] = {"chaine1", "chaineDeux", ...}


    Ici le type est char *, donc on crée un tableau de 32  char *.


    Donc on obtient une zone mémoire de taille = 32*(taille d'un pointeur) octets pour le tableau.


    Dans mon exemple les valeurs de chaque case du tableau seront initialisées avec l'adresse des chaines constantes ("chaine 1", etc).


    Les zones mémoires qui stockent ces chaines constantes ne sont pas forcément contiguës en mémoire.


     


    tab:[ adresse (64bits)  ]---> [ adresse 64 bits ] [ adresse 64 bits ] ... (32 cases de 8 octets)


                                       |                 |


                                       |                 |----> [c] [h] [a] [n] [e] [d] ... (10 octets)


                                       |


                                       |---> [c] [h] [a] [n] [e] [1] (7 octets)


  • mpergandmpergand Membre
    août 2013 modifié #24

    ou plus simplement:



    int tab[2][10];

    printf("ad tab %p ad tab[0] %p ad tab[0][0] %p\n",tab,tab[0],&tab[0][0]);

    Ce qui donne:


     


    ad tab 0xbfffe980 ad tab[0] 0xbfffe980 ad tab[0][0] 0xbfffe980


     


    Tout ça est à  la même adresse.


  • AliGatorAliGator Membre, Modérateur
    Ok merci à  tous pour ces petits rappels, ça ne fait pas de mal.

    En gros, j'a confondu
    char tab[32][32]
    qui alloue une zone mémoire pour 32*32=1024 chars contigus avec
    char str0[32];
    char str1[32];
    ...
    char str31[32];
    char* tab[32] = { str0, str1, ..., str31 };
    qui alloue une zone mémoire pour 32 char* contigus, chaque char* pointant sur une zone mémoire allouée pour de 32 chars.
  • FKDEVFKDEV Membre
    août 2013 modifié #26
    ça arrive même au meilleur. Peut-être, les premiers signes des dégénérescences cellulaires dû à  un processus appelée vieillesse.


    Donc au final la première réponse de Larme était correcte et ça devrait marcher.


    Le probleme ici pouvait etre un probleme de padding dans les structures. On n'a pas vraiment assez de code pour savoir.


    En tous cas, quand on cherche a serialiser des structures en C, il faut etre conscient de ce probleme :


    Les compilateurs ajoutent des octets de padding entre les membres des structures pour aligner chaque membre de la structure sur des adresses multiples de 2,4 ou 8 octets en fonction de leurs optimisations.


    Si on veut éviter cela, il faut utiliser des options de compilations ou des pragma pour ordonner au complateur de ne pas ajouter d'octets de padding. (#pragma pack ou ___attribute(packed)__).


    En clair si vous une structure avec un uint8 suivi d'un uint16, sizeof peut renvoyer 4 au lieu de 3 comme on pourrait s'y attendre.
  • mpergandmpergand Membre
    août 2013 modifié #27


    Donc au final la première réponse de Larme était correcte et ça devrait marcher.




     


    NSData *data = [NSData dataWithBytes:&mesNoms length:sizeof(mesNoms)] 



     


    Ici le compilateur est gentil car l'adresse d'un tableau ça n'existe pas.


    [  EDIT je viens de vérifier ça marche pas


    en fait c'est bizarre si je fais:


     printf("%p %p \n",tab[1],&tab[1]);


    ça affiche la même adresse


    mais char* str=&tab[1];


    produit un warning


    ]


     

    Pour en revenir à  l'erreur de Aligator, je pense que c'est dû au fait qu'il ne pratique pas assez le C ou le C++, ces histoires de tableaux et de pointeurs sont tous sauf intuitifs pour nous humains et qu'il est très facile de se tromper, surtout si l'on ne pratique pas ces langages si souvent.

  • AliGatorAliGator Membre, Modérateur
    août 2013 modifié #28
    Oui ça fait une paye que je n'ai pas fait de C pur, pourtant j'ai de bonnes bases là -dessus, mais les tableaux de tableaux je n'ai jamais su dans quel sens lire ces syntaxes ^^

    Pourtant en Objective-C je fais souvent des
    NSString* const tab[3] = {
    @Toto, @Tata, @Titi
    }
    par exemple, ou encore j'utilise parfois l'initialisation de structures ou de tableaux via champs nommés, comme
    typedef struct {
    CGFloat iPhone;
    CGFloat iPad;
    } UniversalFloat;
    UniversalFloat sz = { .iPhone = 5.f; .iPad = 12.f; }

    CGFloat dirac[21] = { [0 ... 9] = 0, [10] = 1, [11 ... 20] = 0 };
    Qui sont pourtant des astuces purement C que tout le monde ne connais pas... mais les tableaux de tableaux, c'est déjà  moins ma tasse de thé je l'avoue :D Donc merci ça m'a pas fait de mal ces petites révisions ;)

  •  


    typedef struct {



    CGFloat iPhone;
    CGFloat iPad;
    } UniversalFloat;
    UniversalFloat sz = { .iPhone = 5.f; .iPad = 12.f; }

    CGFloat dirac[21] = { [0 ... 9] = 0, [10] = 1, [11 ... 20] = 0 };


    Qui sont pourtant des astuces purement C que tout le monde ne connais pas...




     


    Beuh! c'est quoi ça du Pascal :)


     


    C'est valable avec quelle version du compilateur ?


  • AliGatorAliGator Membre, Modérateur
    août 2013 modifié #30
    C'est du C99.

    Designated Initializers " GCC GNU documentation

    Je l'utilise rarement pour les tableaux, mais très souvent pour les structures, surtout les constantes.

    Par exemple comme je suis très actif contre ceux qui mettent des Magic Numbers partout dans leur code et que j'impose à  tout le monde d'utiliser des constantes plutôt que des valeurs en dur, faut bien parfois déclarer des CGSize ou des CGRect en constantes. Mais CGSizeMake ou CGRectMake ne marchent pas dans ce contexte car sont des fonctions C non-const.


    Donc pour déclarer une CGSize constante, rien de plus simple :
    CGSize const kLabelSize = (CGSize){ .width = 200, .height = 100 };
    Certes, on pourrait juste écrire ceci, ça marche aussi parfaitement
    CGSize const kLabelSize = (CGSize){ 200,100 };
    Mais je trouve la version détaillée plus claire pour éviter de se mélanger les pinceaux.

    Et encore, sur CGSize ça va je peux me passer de préciser les noms des champs, la 2e version me choque pas. Mais sur UIEdgeInsets où je sais jamais si c'est left/top/right/bottom ou top/left/bottom/right ou autre, je précise toujours
    UIEdgeInsets const kInsets = (UIEdgeInsets){ .top = 5, .bottom = 5, .left = 10, .right = 10 };
    ---

    C'est également très utile pour définir une CGRect via son origin et sa size plutôt que de devoir découper ça avec les 4 composantes x,y,width,height :
    CGRect frame = (CGRect){ .origin = newOrigin, .size = kLabelSize };
    Ce qui est quand même plus simple que de devoir préciser les 4 paramètres
    CGRect frame = CGRectMake(newOrigin.x, newOrigin.y, kLabelSize.width, kLabelSize.height);
    alors qu'ils sont issus chacun d'une structure déjà  toute prête newOrigin ou kLabelSize !

    On peut également écrire des choses comme ça, façon KeyPath, mais bon là  je vais rarement voire jamais jusque-là  :
    CGRect frame = (CGRect){ .origin = CGPointZero, .size.width = 200, .size.height = 100 };
  • Super je regarde çà  !


Connectez-vous ou Inscrivez-vous pour répondre.