在Swift 4中为os_log传递可变参数args

smi*_*hco 9 variadic ios swift4

我正在尝试为Swift 4/iOS 11中的os_log编写一个方便的包装器,但是我已经遇到了传递可变参数的艰难战斗.

基本上,我想编写一个如下所示的函数.

static let logger = OSLog(subsystem: "com.example.foo", category: "foobar")
func logError(_ message: StaticString, _ args: Any...) {
    os_log(message, log: logger, type: .error, args)
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,我似乎无法弄清楚传递参数的神奇语法,并且在CVarArg讨论的泥潭中有点迷失.

(...这让我想念Python的splatting语法)

Les*_*rna 8

我还没有找到解决方案,所以这个愚蠢的黑客:

switch args.count {
case 0:
    os_log(message, log: log!, type: type)
case 1:
    os_log(message, log: log!, type: type, args[0])
case 2:
    os_log(message, log: log!, type: type, args[0], args[1])
case 3:
    os_log(message, log: log!, type: type, args[0], args[1], args[2])
default:
    os_log(message, log: log!, type: type, args)
}
Run Code Online (Sandbox Code Playgroud)


smi*_*hco 1

对此做了更多研究。事实证明这os_log实际上是一个 C 宏。这在如何映射到 Swifts 可变参数方面产生了各种各样的问题。

但是,该宏还捕获其他调试信息,并且无论如何都可能不安全。

  • 在 Swift 中,`os_log` 是在 Swift 框架覆盖层中实现的函数。它的工作方式与 C 宏非常不同。在 C 中,对“os_log”的调用实际上在编译时解析了格式字符串。在 Swift 中,它在运行时解析(在框架覆盖中)。这不仅意味着解析不同,因此可能表现不同(例如,在 Swift 3.0 中,它没有正确遵守“public”修饰符),而且还意味着它更慢。 (8认同)