【发布时间】:2016-12-05 06:19:10
【问题描述】:
谁能解释一下 NSLog 和 NSLogv 的区别?我知道NSLog 用于在控制台中打印数据。但是NSLogv是什么?
【问题讨论】:
标签: objective-c swift nslog
谁能解释一下 NSLog 和 NSLogv 的区别?我知道NSLog 用于在控制台中打印数据。但是NSLogv是什么?
【问题讨论】:
标签: objective-c swift nslog
假设您想编写一个类似于 NSLog 的函数,但除了记录它之外,它还将消息保存到一个数组中。你将如何实现它?
如果你写了一个variadic functionvoid MySpecialLog(NSString *format, ...),有人可以像NSLog一样调用你的函数——MySpecialLog(@"Hello %@!", name);——但是访问format之外的额外参数的唯一方法是使用a va_list。 C 或 Obj-C 中没有 splat operator 允许您将它们直接传递给函数内部的 NSLog。
NSLogv 通过va_list 一次性接受所有附加参数来解决这个问题。它的签名是void NSLogv(NSString *format, va_list args)。您可以使用它来构建您自己的 NSLog 包装器。
void MySpecialLog(NSString *format, ...)
NS_FORMAT_FUNCTION(1, 2)
// The NS_FORMAT_FUNCTION attribute tells the compiler to treat the 1st argument like
// a format string, with values starting from the 2nd argument. This way, you'll
// get the proper warnings if format specifiers and arguments don't match.
{
va_list args;
va_start(args, format);
// Do something slightly more interesting than just passing format & args through...
NSString *newFormat = [@"You've called MySpecialLog()! " stringByAppendingString:format];
NSLogv(newFormat, args);
va_end(args);
}
您甚至可以使用相同的技术将 NSLog 包装为 Obj-C 方法。 (而且由于-[NSString initWithFormat:] 有一个类似的变体-initWithFormat:arguments:,你也可以将它包装起来。)
- (void)log:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2)
{
// Similarly to the above, we can pass all the arguments to -initWithFormat:arguments:.
va_list args;
va_start(args, format);
NSString *message = [[NSString alloc] initWithFormat:format arguments:args];
va_end(args);
// Why not both?
va_start(args, format);
NSLogv(format, args);
va_end(args);
}
在 Swift 中,您可以使用接受 CVarArg... 的可变参数函数来做到这一点:
func mySpecialLog(_ format: String, _ args: CVarArg...) {
withVaList(args) {
NSLogv("You've called mySpecialLog()! " + format, $0)
}
}
【讨论】:
NSLog 是varadic function,这意味着它接受可变数量的参数。但有时,程序员会希望实现自己的 varadic 包装函数,该函数在调用 NSLog 之前执行其他操作。
如果 NSLog 是唯一的函数,那将是不可能的,因为您不能将一组可变参数(也称为 va_list)传递给另一个可变参数。
这就是为什么NSLogv 与NSLog 分开存在的原因,NSLog 只是一个接受可变数量参数并将它们传递给NSLogv 的包装器。
【讨论】: