80 votes

Est-il possible de spécifier l'argument position / index dans NSString stringWithFormat?

C# a la syntaxe qui permet de spécifier l'argument de l'indice en chaîne de spécificateur de format, par exemple:

string message = string.Format("Hello, {0}. You are {1} years old. How does it feel to be {1}?", name, age);

Vous pouvez utiliser des arguments plus d'une fois et aussi omettre les arguments qui sont prévus d'être utilisés. Une autre question mentionne la même mise en forme pour le C/C++ sous la forme d' %[index]$[format], par exemple, %1$i. Je n'ai pas été en mesure d'obtenir NSString à pleinement respecter cette syntaxe, car elle ne se comportent bien lors de l'omission des arguments de ce format. Le code suivant ne fonctionne pas comme prévu (EXC_BAD_ACCESS car il tente de déréférencement de l' age paramètre comme une NSObject*):

int age = 23;
NSString * name = @"Joe";
NSString * message = [NSString stringWithFormat:@"Age: %2$i", name, age];

Les arguments de position sont respectées que si il ne manque aucun des arguments de la forme (ce qui semble être une exigence étonnante):

NSString * message = [NSString stringWithFormat:@"Age: %2$i; Name: %1$@", name, age];

Tous ces appels à travailler correctement dans OS X:

printf("Age: %2$i", [name UTF8String], age);
printf("Age: %2$i %1$s", [name UTF8String], age);

Est-il un moyen d'accomplir cela en utilisant NSString en Objective-C / Cocoa? Il serait utile pour la localisation des fins.

123voto

Jim Correia Points 4866

NSString et CFString prennent en charge les arguments réordonnables / de position.

 NSString *string = [NSString stringWithFormat: @"Second arg: %2$@, First arg %1$@", @"<1111>", @"<22222>"];
NSLog(@"String = %@", string);
 

Consultez également la documentation Apple: Fichiers de chaînes

1voto

Werner Altewischer Points 3439

Le code suivant corrige le bogue spécifié dans ce problème. C'est une solution de contournement et renumérote les espaces réservés pour combler les lacunes.

 + (id)stringWithFormat:(NSString *)format arguments:(NSArray*) arguments 
{
    NSMutableArray *filteredArguments = [[NSMutableArray alloc] initWithCapacity:arguments.count];
    NSMutableString *correctedFormat = [[NSMutableString alloc ] initWithString:format];
    NSString *placeHolderFormat = @"%%%d$";

    int actualPlaceholderIndex = 1;

    for (int i = 1; i <= arguments.count; ++i) {
        NSString *placeHolder = [[NSString alloc] initWithFormat:placeHolderFormat, i];
        if ([format rangeOfString:placeHolder].location != NSNotFound) {
            [filteredArguments addObject:[arguments objectAtIndex:i - 1]];

            if (actualPlaceholderIndex != i) {
                NSString *replacementPlaceHolder = [[NSString alloc] initWithFormat:placeHolderFormat, actualPlaceholderIndex];
                [correctedFormat replaceAllOccurrencesOfString:placeHolder withString:replacementPlaceHolder];    
                [replacementPlaceHolder release];
            }
            actualPlaceholderIndex++;
        }
        [placeHolder release];
    }

    if (filteredArguments.count == 0) {
        //No numbered arguments found: just copy the original arguments. Mixing of unnumbered and numbered arguments is not supported.
        [filteredArguments setArray:arguments];
    }

    NSString* result;
    if (filteredArguments.count == 0) {
        //Still no arguments: don't use initWithFormat in this case because it will crash: just return the format string
        result = [NSString stringWithString:format];
    } else {
        char *argList = (char *)malloc(sizeof(NSString *) * [filteredArguments count]);
        [filteredArguments getObjects:(id *)argList];
        result = [[[NSString alloc] initWithFormat:correctedFormat arguments:argList] autorelease];
        free(argList);    
    }

    [filteredArguments release];
    [correctedFormat release];

    return result;
}
 

0voto

Jason Points 11332

Après plus de recherches, il apparaît que Cocoa respecte la syntaxe de position en printf . Par conséquent, un modèle alternatif serait:

 char msg[512] = {0};
NSString * format = @"Age %2$i, Name: %1$s"; // loaded from resource in practice
sprintf(msg, [format UTF8String], [name UTF8String], age);
NSString * message = [NSString stringWithCString:msg encoding:NSUTF8StringEncoding];
 

Cependant, ce serait bien s'il y avait une implémentation de ceci sur NSString.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X