使用 NS_REQUIRES_NIL_TERMINATION 检查参数是否以 nil 结尾,可变参数非 nil 结尾时会造成崩溃。
- (void)sumup:(NSNumber *)num,... NS_REQUIRES_NIL_TERMINATION {
NSNumber *rst = @0;
if (num) {
rst = @(rst.floatValue + num.floatValue);
// 定义一个用于指向个数可变的参数列表指针
va_list args;
// 从num的下一个元素开始
va_start(args, num);
NSNumber *next = nil;
// 循环获取参数列表中的参数
while ((next = va_arg(args, NSNumber *))) {
rst = @(rst.floatValue + next.floatValue);
}
// 清空参数列表,并置参数指针args无效
va_end(args);
}
NSLog(@"%@",num);
}
使用 format 函数
类似 NSString 的 xxxWithFormat: 系列方法
宏 NS_FORMAT_FUNCTION(1, 2) 表示第一个是 format string,第二个参数开始是对应 format string 的参数列表
- (void)logFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2) {
va_list args;
va_start(args, format);
NSString *log = [[NSString alloc] initWithFormat:format arguments:args];
va_end(args);
// NSLog(@"%@",log);
printf("%s", log.UTF8String);
if (self.delegate && [self.delegate respondsToSelector:@selector(logInfo:)]) {
[self.delegate logInfo:log];
}
}
- (void)logFormat:(const char *)format, ... __printflike(1, 2) {
int len;
std::string str;
va_list args;
char buffer[4 * 1024];
va_start(args, format);
if ((len = vsnprintf(buffer, sizeof(buffer), format, args)) > 0) {
if (len < sizeof(buffer)) {
str = buffer;
}
else {
int maxsz = len + 1;
char* buffer = (char*)malloc(maxsz);
if (buffer) {
len = vsnprintf(buffer, maxsz, format, args);
if (len > 0 && len < maxsz) str = buffer;
free(buffer);
}
}
}
va_end(args);
if (self.delegate && [self.delegate respondsToSelector:@selector(logInfo:)]) {
[self.delegate logInfo:[NSString stringWithUTF8String:str.c_str()]];
}
}