代理包装 iOS 14 记录器 class

Proxy Wrap the iOS 14 Logger class

我有一个可在 iOS12 上使用的应用程序。过去我使用过优秀的 CocoaLumberjack,但我想转到本机 Logger class.

我很高兴不为旧 iOS 版本收集日志,但我希望该应用程序 运行 在那里。

有没有什么好方法可以避免到处#available调用?通常我喜欢 #available,但对于日志记录来说它很笨重

if #available(iOS 14.0, *) {
     logger.info("Setting person from \(self.person, privacy: .public) to \(newValue, privacy: .public)")
}

如果我包装 Logger class,我无法编译它,因为日志系统有编译时间限制:

import os

public class Logger {

    @available(iOS 14.0, *)
    static let logger = os.Logger(subsystem: "com.progress", category: "ProgressKit")

    public static func debug(_ input: String) {
        if #available(iOS 14.0, *) {
            logger.debug(OSLogMessage(stringLiteral: input)) //  Fails: Argument must be a string interpolation
        } else {
            print(input)
        }
    }
}

有没有一种方法可以使用新系统来做到这一点,而无需到处都使用 #available 语句??

问题是不可用。问题是,正如您所发现的,Logger 日志命令的参数不是字符串。它是一个私有 class ,可以用文字字符串表示。因此,您不能将字符串传递到包装器并将其中继到记录器。您必须直接使用文字字符串调用 Logger 方法。

但是,Logger 本身只是 os_log 的巧妙包装器,它确实接受一个字符串。所以你可以改用它。或者,您可以像您建议的那样,在任何地方都使用可用性和其他向后兼容技术。

编译器中确实有一个特殊情况,以确保 OSLogMessage 只能从字符串文字构造。

https://github.com/apple/swift/pull/31109/files

这意味着无法包装它,您不得不:

  1. 通过放弃对 Big Sur 之前的所有内容的支持来加速旧设备的淘汰,并直接使用闪亮的新 API,或者
  2. 不要使用它,使用 os_log API,尽管它们可能很丑陋。