2

En ce moment, j'ai ceci:fonction VARIADIC en Objective C qui accepte les primitives

// .h 
- (NSArray *)createNumberArrayWithInts:(NSInteger)firstArg, ... 
    NS_REQUIRES_NIL_TERMINATION; 

// .m 
- (NSArray *)newNumberArrayWithInts:(NSInteger)firstArg, ... { 
    NSMutableArray *lCreatedArray = [NSMutableArray alloc]; 

    va_list args; 
    va_start(args, firstArg); 
    for (NSInteger arg = firstArg; arg != nil; arg = va_arg(args, NSInteger)) { 
     NSNumber *lTempNumberObject = [[NSNumber alloc] initWithInteger:arg]; 
     [lCreatedArray addObject:lTempNumberObject]; 
     [lTempNumberObject release]; 

    } 
    va_end(args); 

    NSArray *lImmutableArray = [[NSArray alloc] initWithArray:lCreatedArray]; 
    [lCreatedArray release]; 

    return lImmutableArray; 
} 

mais la comparaison à zéro est incorrect parce que ints ne sont pas des objets. Utiliser NSNumbers serait vaincre le but pour moi car j'essaie de ne pas allouer les objets en dehors de cette méthode.

quoi faire?

Répondre

4

Ce problème existe également en C. Si vous utilisez des entiers comme celui-ci, vous ne pouvez pas utiliser de sentinelle (comme vous l'avez découvert). Ce que la plupart des gens font est de définir le premier argument comme la taille à la place. Ainsi, votre puissance prototype ressemble à quelque chose comme:

- (NSArray *)createNumberArrayWithInts:(NSUInteger)length, ... 

Le problème évident avec ce genre de conception est que le compilateur ne peut pas vérifier. Si vous faites une erreur avec la taille, vous pourriez avoir des ennuis, mais c'est exactement le même genre de problème que vous auriez en C même si vous avez passé un tableau d'ints ou quelque chose comme ça. C'est à l'appelant de s'assurer que la taille est correcte.

Une autre solution serait d'avoir un int illégal comme sentinelle. Alors, choisissez quelque chose comme MAX_INT ou autre chose. Lorsque vous trouvez cela, arrêtez de lire la liste. Encore une fois, cependant, vous ne pouvez pas vraiment avertir le compilateur ...

+1

Je pense que, si le type d'entier est 'NSInteger', la meilleure valeur sentinelle est probablement' NSNotFound' qui est devrait être la plus grande valeur possible exprimable en tant que 'NSInteger'. – JeremyP

+1

@JeremyP: En fait, puisqu'il utilise un NSInteger, il devrait probablement utiliser NSIntegerMax. NSNotFound est en fait défini comme NSIntegerMax, mais IMO, en utilisant NSIntegerMax est plus à propos. Honnêtement, cependant, je pense qu'en ajoutant le nombre d'entiers, le premier argument requis est la meilleure solution. –

+0

Je suis allée et venir sur ce qui est le mieux dans les 2 dernières heures. J'utilise la méthode NSNotFound en ce moment, mais pourquoi préféreriez-vous la longueur comme premier argument requis? (J'ai seulement choisi NSNotFound pour la lisibilité) – griotspeak

3

Ok pour ceux d'entre vous éberlués par les primitives comme VA_ARGS ... voici une réponse logique pour tous. Je présente ici une catégorie sur CALayer qui prend une longueur variable « liste » des CAConstraintAttribute (s), et les applique à la couche ..

@interface CALayer (VariadicConstraints) 
- (void)addConstraintsRelSuper:(CAConstraintAttribute)first,...; 
/* REQUIRES NSNotFound termination */ 
@end 

@implementation CALayer (VariadicConstraints) 
- (void)addConstraintsRelSuper:(CAConstraintAttribute)first,...{ /* REQUIRES NSNotFound termination */ 
    va_list args; va_start(args, first); 
    for (NSUInteger arg = first; arg != NSNotFound; 
        arg = va_arg(args, NSUInteger)) 
    { [self addConstraint:CAConstRelSuper(arg)]; } 
    va_end(args); 
} 
@end 

Maintenant, en ajoutant des contraintes de la couche est simplifiée pour ...

[layer addConstraintsRelSuper:kCAConstraintMaxX, kCAConstraintHeight, NSNotFound]; 

NSLog layer.constraints ➞ "[MaxX = superlayer.MaxX]", "[Taille = superlayer.Height]"

... à partir de ce qui aurait auparavant été plusieurs centaines de caractères.

Et pour être complet .. voici ma macro pour CAConstRelSuper ...

#define CAConstRelSuper(attr) [CAConstraint constraintWithAttribute: \ 
attr relativeTo:@"superlayer" attribute:attr]