1. Welcome to the new MacRumors forums. See our announcement and read our FAQ

Resolved variable arguments help (Cocoa format string)

Discussion in 'Mac Programming' started by ArtOfWarfare, Apr 30, 2013.

  1. ArtOfWarfare, Apr 30, 2013
    Last edited: May 1, 2013

    macrumors 603

    ArtOfWarfare

    #1
    I've written a category on NSString that includes this:

    Code:
    // 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:

    Code:
    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:
    Code:
    "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:

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

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

    Code:
    + (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:

    Code:
    + (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:
    Is the canonical locale what I want?

    Afterwards it says:
    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

    Code:
    + (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.
     
  2. macrumors G5

    gnasher729

    #2
    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.
     

Share This Page