swift - Xcode 12 和 OSLog (os.log):包装 OSLogMessage 会导致编译错误:参数必须是字符串插值
问题描述
在 Xcode 12 / iOS 14 中,OSLog 获得了对字符串插值的支持(耶!)。但是仍然不可能附加挂钩以轻松登录到其他渠道,例如 Crashlytics。
所以我想我会做一个简单的包装器并传递参数。然而,关于字符串插值似乎发生了一些神奇的事情。
提供的新 Logger 类,它带有一个OSLogMessage
as 参数,可以按如下方式使用:
let someVar = "some var"
let logger = Logger(subsystem: "com.my.app", category: "UI")
logger.error("some message")
logger.error("some message with default var: \(someVar)")
logger.error("some message with private var: \(someVar, privacy: .private)")
logger.error("some message with private var: \(someVar, privacy: .private(mask: .hash))")
logger.error("some message with public var: \(someVar, privacy: .public)")
包装新的 Logger 结构
所以让我们把它包装在一个结构中:
struct MyLogger {
let logger = Logger(subsystem: "com.my.app", category: "UI")
func error(_ message: OSLogMessage) {
logger.error(message)
}
}
相同的签名,但不幸的是,编译器不允许这样做:
ERROR: Argument must be a string interpolation
此外,尝试调用我的结构也会导致一个奇怪的特定编译器错误:
let logger = MyLogger()
let value = "value"
logger.error("Some log message \(value, privacy: .public)")
产量:
String interpolation cannot be used in this context; if you are calling an os_log function, try a different overload
直接调用os_log(_: OSLogMessage)
而不是新结构会给出相同的结果。
有没有办法解决这个问题?我错过了什么吗?
解决方案
日志 API 使用特殊的编译器功能在编译时评估隐私级别。正如诊断所说,您必须使用“OSLogPrivacy”的静态(即在编译时已知)方法或属性;它不能是在运行时评估的变量。这意味着如果不使用编译器内部功能,您将无法为这些 API 创建自己的包装器。
推荐阅读
- rabbitmq - 将 RabbitMQ 与动态队列和持久消息一起使用时的性能
- android - 如何使 PopupWindow 在背景触摸时不关闭,并且仍然能够在其 TextView 中输入文本
- aws-cli - 描述读取变量的自动缩放组
- android - 在画布上绘图时路径弧比直线弧粗
- dart - Flutter 有类似 Redux 的东西吗?
- excel - 使用任务计划程序在 Excel 中运行 selenium vba 宏时,如何修复“运行时错误 429:ActiveX 组件无法创建对象”错误?
- c# - 有没有一种最有效的方法可以在 C# 中读取/写入最多 10GB 的二进制文件?
- expect - 在期望脚本中循环以发送多个发送命令
- php - Laravel/Heroku,没有这样的文件或目录用于会话
- c++ - 递归变体输出编译但在运行时出现段错误