web-dev-qa-db-fra.com

CGRect syntaxe que je n'ai jamais vue auparavant

J'ai vu la syntaxe ci-dessous dans certains exemples de code et je ne suis pas sûr de le comprendre.

 CGRect imageRect = (CGRect){.size = baseImage.size};

S'agit-il simplement d'une manière abrégée d'initialiser une CGRect équivalente à:

 CGRect imageRect = CGRectMake(0,0,baseImage.size.width, baseImage.size.height);

Y a-t-il un avantage à cette syntaxe en dehors d'un peu moins de frappe?

26
No Grabbing

C'est La syntaxe de l'initialiseur C99 . Vous pouvez l'utiliser avec n'importe quelle structure.

L’objectif principal d’un Objective-C est qu’il vous donne une syntaxe très semblable à Objective-C, dans laquelle les champs sont proches des valeurs plutôt qu’impliqués par le positionnement. (Cela ne veut pas dire que c'est intentionnellement similaire, ou que c'est le seul avantage. Mais c'est Nice.)

C'est parfois légèrement more dactylographie, mais je l'utilise partout maintenant.

Considérer:

CGRect a = CGRectMake(a+c/2, b+d/2, c, d);

Afin de comprendre ceci, vous devez comprendre l'ordre des paramètres. Vous devez également pouvoir saisir facilement les virgules avec vos yeux. Dans ce cas, c'est assez facile, mais si les expressions étaient plus compliquées, vous les stockeriez probablement dans une variable temporaire en premier.

La manière C99:

CGRect a = (CGRect){
    .Origin.x = a+c/2,
    .Origin.y = b+d/2,
    .size.width = c,
    .size.height = d
};

C'est plus long, mais c'est plus explicite. Il est également très facile de suivre ce qui est assigné à quoi, peu importe la longueur de l'expression. Cela ressemble aussi plus à une méthode Objective-C. Après tout, si CGRect était une classe, cela ressemblerait probablement à ceci:

CGRect *a = [[CGRect alloc] initWithOriginX:x originY:y width:w height:h];

Vous pouvez aussi faire des choses comme ça:

CGRect a = (CGRect){
    .Origin = myOrigin,
    .size = computedSize
};

Ici, vous construisez un rectangle en utilisant CGPoint et CGSize. Le compilateur comprend que .Origin attend une CGPoint et .size attend une CGSize. Vous avez fourni cela. Tout est de la sauce.

Le code équivalent serait CGRectMake(myOrigin.x, myOrigin.y, size.width, size.height). En utilisant CGRectMake, vous n’exprimez plus le même genre de signification pour le compilateur. Cela ne peut pas vous empêcher d'attribuer une partie de la taille à l'origine. Cela ne vous empêchera pas non plus d'affecter la largeur à la hauteur. Cela ne vous donne même pas une bonne idée de ce qui est le X et le Y; si vous avez utilisé des API fournissant d'abord des coordonnées verticales, vous vous tromperez.

Vous pouvez également affecter des parties d'une structure et des flottants:

CGRect a = (CGRect){
    .Origin = myOrigin,
    .size.width = c,
    .size.height = d
};

La fonction CGRectMake est antérieure à C99. Je n'ai aucune preuve à cet effet, mais je pense que si C99 était arrivé en premier CGRectMake n'existerait probablement pas du tout; c'est le genre de fonction croustillante que vous écrivez lorsque votre langue n'a aucun moyen direct d'effectuer l'initialisation. Mais maintenant c'est le cas.

Fondamentalement, si vous l'utilisez pendant un moment, vous finirez probablement par préférer la syntaxe C99. C'est plus explicite, plus flexible, plus objectif et plus difficile à bousiller.

Malheureusement, à partir de la version 4.6, Xcode ne complétera pas automatiquement les noms de champs de la structure dans la liste des initialiseurs de champs C99.

41
Steven Fisher

Ce n'est pas simplement une syntaxe abrégée, mais est également utile lorsque vous souhaitez modifier uniquement la taille et pas l'origine dans CGRect et vice versa.

Ex: je veux changer uniquement la taille et la position a une syntaxe compliquée et je ne veux pas la changer. Noramlly, je ferais

CGRect imageRect = CGRectMake(Sprite.Origin.x,Sprite.Origin.y,40, 60);

Avec l'autre syntaxe, je ferais

CGRect imageRect = (CGRect){.size = Sprite.size};

nous pouvons aussi utiliser directement les méthodes d’addition, de soustraction et de multiplication .

 CGRect imageRect = (CGRect){.size = ccpAdd(Sprite.size,addsize)};

J'espère que cela t'aides

4
Bharat Gulati

il semble que le style C99/GCC initialise - http://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html

0
blub