【问题标题】:Difference between NSLog and NSLogvNSLog 和 NSLogv 的区别
【发布时间】:2016-12-05 06:19:10
【问题描述】:

谁能解释一下 NSLog 和 NSLogv 的区别?我知道NSLog 用于在控制台中打印数据。但是NSLogv是什么?

【问题讨论】:

    标签: objective-c swift nslog


    【解决方案1】:

    假设您想编写一个类似于 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 包装器。

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

    您甚至可以使用相同的技术将 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,..."在你的第一个代码示例的第一行吗?
    • @jtbandes:没错。您使用 NSLogv 构建了一个NSLog 替代品,因此“如果您没有NSLogv” 对我来说听起来很误导。
    【解决方案2】:

    一般来说,v 的后缀意味着函数将va_list 作为参数,而不是可变参数列表。

    NSLogNSLogv 就是这种情况:

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

    这在某些非常特殊的情况下很有用,您需要“包装”一个接受可变参数的函数。如果你需要它,你会知道的。否则,您可以放心地忽略它。

    【讨论】:

    • 请解释“你需要“包装”一个接受可变参数的函数”
    【解决方案3】:

    NSLogvaradic function,这意味着它接受可变数量的参数。但有时,程序员会希望实现自己的 varadic 包装函数,该函数在调用 NSLog 之前执行其他操作。

    如果 NSLog 是唯一的函数,那将是不可能的,因为您不能将一组可变参数(也称为 va_list)传递给另一个可变参数。

    这就是为什么NSLogvNSLog 分开存在的原因,NSLog 只是一个接受可变数量参数并将它们传递给NSLogv 的包装器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      • 1970-01-01
      • 2013-08-07
      • 2011-10-20
      • 2020-01-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多