The difference between NSLog and NSLogv

Can someone explain the difference between NSLog and NSLogv? I know that NSLog used to print data to the console. But what is NSLogv ?

+5
source share
3 answers

Suppose you want to write a function similar to NSLog, but which also stores the message in an array in addition to registering it. How do you implement this?

If you write the variation function void MySpecialLog(NSString *format, ...) , someone can call your function the same way as NSLog - MySpecialLog(@"Hello %@!", name); , but the only way to access additional arguments outside of format is a va_list . There is no splat operator in C or Obj-C allowing you to pass them directly to NSLog inside a function.

NSLogv solves this problem by simultaneously accepting all additional arguments through va_list . Its signature is void NSLogv(NSString *format, va_list args) . You can use it to create 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 use the same method to port the NSLog using the Obj-C method. (And since -[NSString initWithFormat:] has a similar option 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 variational function that takes CVarArg... :

 func mySpecialLog(_ format: String, _ args: CVarArg...) { withVaList(args) { NSLogv("You've called mySpecialLog()! " + format, $0) } } 
+7
source

In essence, the suffix v means that the function takes va_list as an argument, not a list of variational arguments.

This applies to NSLog and NSLogv :

 void NSLog(NSString *format, ...); void NSLogv(NSString *format, va_list args); 

This is useful in some very specific situations when you need to "wrap" a function that accepts variable arguments. If you need it, you will find out. Otherwise, you can safely ignore it.

+1
source

NSLog is a varadic function , which means that it takes a variable number of arguments. But sometimes programmers will want to implement their own varadic shell function, which does something even before NSLog called.

If NSLog was the only function, that would be impossible, because you cannot pass a set of varidic arguments (aka a va_list ) to another varadic function.

This is why NSLogv exists separately from NSLog , which is just a wrapper that takes a variable number of arguments and passes them to NSLogv .

+1
source

Source: https://habr.com/ru/post/1260799/


All Articles