在函数中迭代可变数量的参数而不传递nil

时间:2014-05-07 04:01:04

标签: objective-c c

我和很多人一样,经常要查找日期格式化程序的日期代码。我决定制作一个文件,让我更容易记住它们。我包含了一个可读性函数,我声明如下:

NSString * dateFormatString(NSString * string1, ...) {

    // Parse out Args
    va_list args;
    va_start(args,string1);

    // Set up our Format String
    NSMutableString * formatString = [NSMutableString string];

    // Build Format string
    for (NSString * arg = string1; arg != nil; arg = va_arg(args, NSString*)) {
        [formatString appendString:arg];
    }

    va_end(args);

    return formatString;
}

所以,我可以像这样编程NSDateFormatter

dateFormatter.dateFormatString = dateFormatString(DKDayOfWeekFull, @", ", DKMonthNameFull, @" ", DKDayOfMonthComplete, nil);

你可以通过声明来实现几乎相同的事情:

[NSString stringWithFormat:@"%@, %@ %@", DKDayOfWeekFull, DKMonthNameFull, DKDayOfMonthComplete];

但是,如果您描述的日期包含更多变量,例如“星期六,2006年1月14日上午7:52”,则必须是:

 NSString * dateFormatterString = [NSString stringWithFormat:@"%@, %@ %@ %@ 'at' %@:%@ %@", DKDayOfWeekAbbreviated, DKMonthNameAbbreviated, DKDayOfMonthComplete, DKYearComplete, DKHour12hrComplete, DKMinutes2Digits, DKAmPm];

我个人认为这样可读性更高:

NSString * dateFormatterString = dateFormatString(DKDayOfWeekAbbreviated, @", ", DKMonthNameAbbreviated, @" ", DKDayOfMonthComplete, @" ", DKYearComplete, @"'at' ", DKHour12hrComplete, @":", DKMinutes2Digits, @" ", DKAmPm, nil);

问题

我更喜欢一种迭代变量的方法,而不必将nil传递给函数。是否有另一种方法来迭代变量参数列表,而不是:

for (NSString * arg = string1; arg != nil; arg = va_arg(args, NSString*)) {
    [formatString appendString:arg];
}

2 个答案:

答案 0 :(得分:2)

我假设你想说dateFormatter.dateFormat = ...,因为NSDateFormatter没有dateFormatString属性。

我认为DKDayOfWeekAbbreviated是一个定义为@"E"的字符串常量,DKDayOfWeekFull@"EEEE",依此类推,基于UTS #35

如果是这样,那么这是一种不同的方法。像这样定义你的常量:

#define DKDayOfWeekAbbreviated @"E"
#define DKDayOfWeekFull @"EEEE"
#define DKMonthNameFull @"MMMM"
#define DKDayOfMonthComplete @"dd"

然后使用编译时字符串连接来构建字符串。编译器合并两个相邻的字符串常量。例如,"hello " "world"变为"hello world"@"hello " @"world"变为@"hello world"。实际上,您可以省略第二个及以后的@字符,因此@"hello " "world"变为@"hello world"

因此:

dateFormatter.dateFormat = DKDayOfWeekFull ", " DKMonthNameFull " " DKDayOfMonthComplete;

您不需要辅助功能或varargs。

答案 1 :(得分:1)

使用标准C语法支持变量参数的唯一方法是执行您正在执行的操作。

但您还有另一种选择 - 使用NSArray

您的功能变为:

NSString * dateFormatString(NSArray *strings) {
    // Set up our Format String
    NSMutableString * formatString = [NSMutableString string];

    // Build Format string
    for (NSString * arg in strings) {
        [formatString appendString:arg];
    }

    return formatString;
}

或只是做:

NSString * dateFormatString(NSArray *strings) {
    return [strings componentsJoinedByString:@""];
}

你这样称呼它:

dateFormatter.dateFormatString = dateFormatString(@[ DKDayOfWeekFull, @", ", DKMonthNameFull, @" ", DKDayOfMonthComplete ]);

nil无需使用现代NSArray语法。