PDA

View Full Version : [Resolved] variable arguments help (Cocoa format string)




ArtOfWarfare
Apr 30, 2013, 01:35 PM
I've written a category on NSString that includes this:

// From what I can tell, NSString's default localizedStringWithFormat: method
// doesn't actually do a lookup on Localizable.strings. So I wrote this which
// does the lookup and then does everything the default one does.

+ (NSString *)fullyLocalizedStringWithFormat:(NSString *)format, ...
{
NSString *lookup = NSLocalizedString(format, @"");
NSString *fullyLocalized;

va_list arguments;
va_start(arguments, format);

NSLogv(lookup, arguments);
fullyLocalized = [NSString localizedStringWithFormat:lookup, arguments];

va_end(arguments);
return fullyLocalized;
}

If I invoke it with:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateStyle = NSDateFormatterShortStyle;
dateFormatter.timeStyle = NSDateFormatterNoStyle;
dateFormatter.locale = [NSLocale currentLocale];
[NSString fullyLocalizedStringWithFormat:@"Replaced %@", [dateFormatter stringFromDate:[NSDate date]]];

And I have this in Localizable.strings:
"Replaced %@" = "Batteries were Last Full: %@";

Then NSLogv will (today in the US) properly print out
"Batteries were Last Full: 4/30/13"

But on the very next line, localizedStringWithFormat: crashes my program with EXC_BAD_ACCESS

If I replaced localizedStringWithFormat: with stringWithFormat:, it crashes just the same.

It also crashes if I replace it with:

fullyLocalized = [[NSString alloc] initWithFormat:lookup arguments:arguments];
Suggestions?

Edit: I found one thing that doesn't crash so far:

+ (NSString *)fullyLocalizedStringWithFormat:(NSString *)format, ...
{
NSString *lookup = NSLocalizedString(format, @"");
NSString *fullyLocalized;
va_list arguments;
va_start(arguments, format);
//NSLogv(lookup, arguments);
fullyLocalized = [[NSString alloc] initWithFormat:lookup arguments:arguments];
va_end(arguments);
return fullyLocalized;
}

NSLogv can't be there or it doesn't work. I still can't make it localize the arguments at the same time, though (IE, use [localizedStringWithFormat:lookup, arguments]; ).

Exit 2x: This appears to work, but the documentation confuses me a little so I'm not sure if it's actually working the way I want it to or if it just looks like it is for my local:

+ (NSString *)fullyLocalizedStringWithFormat:(NSString *)format, ...
{
NSString *lookup = NSLocalizedString(format, @"");
NSString *fullyLocalized;
va_list arguments;
va_start(arguments, format);
fullyLocalized = [[NSString alloc] initWithFormat:lookup
locale:nil
arguments:arguments];
va_end(arguments);
return [fullyLocalized autorelease];
}

The documentation for initWithFormat:locale:arguments: says, pertaining to locale:
If this value is nil, uses the canonical locale.

Is the canonical locale what I want?

Afterwards it says:
To use a dictionary containing the current user's locale, you can use [[NSUserDefaults standardUserDefaults] dictionaryRepresentation].

The current user's locale is exactly what I want, but I'm really confused how exactly the method they provide would do anything like that... standardUserDefaults doesn't contain anything about the current user's locale (as far as I know), so it makes no sense to me and sounds like a typo.

Edit 3x: I've decided to use

+ (NSString *)fullyLocalizedStringWithFormat:(NSString *)format, ...
{
NSString *lookup = NSLocalizedString(format, @"");
NSString *fullyLocalized;
va_list arguments;
va_start(arguments, format);
fullyLocalized = [[NSString alloc] initWithFormat:lookup
locale:[NSLocale currentLocale]
arguments:arguments];
va_end(arguments);
return [fullyLocalized autorelease];
}

It appears to work, it doesn't confuse me, and it seems to make sense.



gnasher729
May 1, 2013, 02:22 AM
You can't use a va_list twice in two calls as you did in your very first method; the first called function will modify it, and then the second one won't work. You need to use a sequence va_start / use it / va_end, va_start, use it again, va_end.