构建自定义记录器:所有类型的自定义Swift字符串插值
我想重现新的Swift日志功能的行为,其中字符串中的插值显示为构建自定义记录器:所有类型的自定义Swift字符串插值,swift,string,string-interpolation,Swift,String,String Interpolation,我想重现新的Swift日志功能的行为,其中字符串中的插值显示为,而不是我在应用程序中使用的自定义日志的实际值 例如: let accountNumber = 12345 log("User account number: \(accountNumber)") // User account number: 12345 ← leaking personal information 相反,我希望得到以下结果: // User account number: <pri
,而不是我在应用程序中使用的自定义日志的实际值
例如:
let accountNumber = 12345
log("User account number: \(accountNumber)")
// User account number: 12345 ← leaking personal information
相反,我希望得到以下结果:
// User account number: <private>
您可以创建一个自定义类型(我们称之为
SecureMessage
),即ExpressibleByStringInterpolation
(以及CustomStringConvertible
),并让log
函数将其作为其消息参数:
func log(_ message: SecureMessage) {
print("\(message)")
}
let accountNumber = 12345
log("User account number: \(accountNumber)")
现在,我们可以定义SecureMessage
:
struct SecureMessage: ExpressibleByStringInterpolation,
CustomStringConvertible {
struct StringInterpolation: StringInterpolationProtocol {
var output = ""
init(literalCapacity: Int, interpolationCount: Int) { }
mutating func appendLiteral(_ literal: String) {
output.append(literal)
}
mutating func appendInterpolation<T>(_ str: T) {
output.append("<private>")
}
}
let description: String
init(stringLiteral value: String) {
description = value
}
init(stringInterpolation: StringInterpolation) {
description = stringInterpolation.output
}
}
并更改appendInterpolation
方法,以获取具有某些默认隐私值的隐私参数:
mutating func appendInterpolation<T: LosslessStringConvertible>(_ str: T, privacy: PrivacyLevel = .private) {
switch privacy {
case .private:
output.append("<private>")
case .public:
output.append(String(str))
}
}
非常感谢您快速而彻底的回答!!
enum PrivacyLevel {
case `public`, `private`
}
mutating func appendInterpolation<T: LosslessStringConvertible>(_ str: T, privacy: PrivacyLevel = .private) {
switch privacy {
case .private:
output.append("<private>")
case .public:
output.append(String(str))
}
}
log("Hidden account number: \(accountNumber)") // private by default
log("Visible account number: \(accountNumber, privacy: .public)")