Can anyone explain the difference between NSLog and NSLogv? I know NSLog
is used to print data in the console. But what is NSLogv
?
Suppose you want to write a function similar to NSLog, but which also saves the message to an array in addition to logging it. How would you implement this?
If you write a 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 in C or Obj-C allowing you to pass them directly to NSLog inside the function.
NSLogv solves this problem by accepting all the additional arguments at once via a va_list
. Its signature is void NSLogv(NSString *format, va_list args)
. You can use it to build your own NSLog wrappers.
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);
}
You can even use the same technique to wrap NSLog with an Obj-C method. (And since -[NSString initWithFormat:]
has a similar variant called -initWithFormat:arguments:
, you can wrap it too.)
- (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
In Swift, you can do this with a variadic function accepting CVarArg...
:
func mySpecialLog(_ format: String, _ args: CVarArg...) {
withVaList(args) {
NSLogv("You've called mySpecialLog()! " + format, $0)
}
}
Generally speaking, a suffix of v
means that a function takes a va_list
as an argument, instead of a variadic argument list.
This is the case for NSLog
and NSLogv
:
void NSLog(NSString *format, ...);
void NSLogv(NSString *format, va_list args);
This is useful in certain very specific situations where you need to "wrap" a function that takes variadic arguments. If you need it, you'll know. Otherwise, you can safely ignore it.
NSLog
is a varadic function, which means it takes a variable number of arguments. But sometimes, programmers will want to implement their own varadic wrapper function which does something else before calling NSLog
.
If NSLog
was the only function, that wouldn't be possible because you can't pass a set of varadic arguments (aka a va_list
) to another varadic function.
That's why NSLogv
exists separately from NSLog
, which is just a wrapper that accepts a variable number of arguments and passes them to NSLogv
.
© 2022 - 2024 — McMap. All rights reserved.