NSLog 和 NSLogv 的区别
Difference between NSLog and NSLogv
谁能解释一下 NSLog 和 NSLogv 的区别?我知道 NSLog
用于在控制台打印数据。但是 NSLogv
是什么?
一般来说,v
的后缀表示函数采用 va_list
作为参数,而不是可变参数列表。
void NSLog(NSString *format, ...);
void NSLogv(NSString *format, va_list args);
这在某些非常特殊的情况下很有用,在这些情况下,您需要 "wrap" 一个接受可变参数的函数。如果你需要它,你就会知道。否则,您可以放心地忽略它。
假设您要编写一个类似于 NSLog 的函数,但除了记录消息外,它还会将消息保存到数组中。您将如何实施?
如果你用 C 或 Obj-C 编写 variadic function void MySpecialLog(NSString *format, ...)
, someone can call your function just like NSLog — MySpecialLog(@"Hello %@!", name);
— but the only way to access the extra arguments beyond format
is with a va_list
. There's no splat operator 允许你将它们直接传递给函数内的 NSLog。
NSLogv 通过 va_list
一次接受所有附加参数来解决这个问题。它的签名是void NSLogv(NSString *format, va_list args)
。您可以使用它来构建您自己的 NSLog 包装器。
Obj-C
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);
}
您甚至可以使用相同的技术通过 Obj-C 方法包装 NSLog。 (因为 -[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
在 Swift 中,您可以使用可变函数接受 CVarArg...
:
func mySpecialLog(_ format: String, _ args: CVarArg...) {
withVaList(args) {
NSLogv("You've called mySpecialLog()! " + format, [=12=])
}
}
NSLog
是一个 varadic function,这意味着它需要可变数量的参数。但有时,程序员会想要实现他们自己的 varadic 包装函数,该函数在调用 NSLog
.
之前执行其他操作
如果 NSLog
是唯一的函数,那将是不可能的,因为您不能将一组可变参数(又名 va_list
)传递给另一个可变参数函数。
这就是为什么 NSLogv
与 NSLog
分开存在的原因,它只是一个包装器,它接受可变数量的参数并将它们传递给 NSLogv
。
谁能解释一下 NSLog 和 NSLogv 的区别?我知道 NSLog
用于在控制台打印数据。但是 NSLogv
是什么?
一般来说,v
的后缀表示函数采用 va_list
作为参数,而不是可变参数列表。
void NSLog(NSString *format, ...);
void NSLogv(NSString *format, va_list args);
这在某些非常特殊的情况下很有用,在这些情况下,您需要 "wrap" 一个接受可变参数的函数。如果你需要它,你就会知道。否则,您可以放心地忽略它。
假设您要编写一个类似于 NSLog 的函数,但除了记录消息外,它还会将消息保存到数组中。您将如何实施?
如果你用 C 或 Obj-C 编写 variadic function void MySpecialLog(NSString *format, ...)
, someone can call your function just like NSLog — MySpecialLog(@"Hello %@!", name);
— but the only way to access the extra arguments beyond format
is with a va_list
. There's no splat operator 允许你将它们直接传递给函数内的 NSLog。
NSLogv 通过 va_list
一次接受所有附加参数来解决这个问题。它的签名是void NSLogv(NSString *format, va_list args)
。您可以使用它来构建您自己的 NSLog 包装器。
Obj-C
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);
}
您甚至可以使用相同的技术通过 Obj-C 方法包装 NSLog。 (因为 -[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
在 Swift 中,您可以使用可变函数接受 CVarArg...
:
func mySpecialLog(_ format: String, _ args: CVarArg...) {
withVaList(args) {
NSLogv("You've called mySpecialLog()! " + format, [=12=])
}
}
NSLog
是一个 varadic function,这意味着它需要可变数量的参数。但有时,程序员会想要实现他们自己的 varadic 包装函数,该函数在调用 NSLog
.
如果 NSLog
是唯一的函数,那将是不可能的,因为您不能将一组可变参数(又名 va_list
)传递给另一个可变参数函数。
这就是为什么 NSLogv
与 NSLog
分开存在的原因,它只是一个包装器,它接受可变数量的参数并将它们传递给 NSLogv
。