Difference between NSLog and NSLogv

后端 未结 3 1519
遥遥无期
遥遥无期 2021-01-12 11:44

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

3条回答
  •  执笔经年
    2021-01-12 12:29

    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)
        }
    }
    

提交回复
热议问题