【问题标题】:Swift rewriting init(format: String, _ arguments: CVarArg...)Swift重写init(格式:字符串,_参数:CVarArg ...)
【发布时间】:2020-06-07 09:57:58
【问题描述】:

我正在尝试重写在基础中找到的标准 String(format, arguments) 方法,该方法接受一个字符串并将包含 %i 的所有值替换为整数,将包含 %@ 的所有值替换为字符串和一系列类型。 https://developer.apple.com/documentation/swift/string/3126742-init

由于我不知道 c 我从

转换了初始化程序
init(format: String, _ arguments: CVarArg) {

init(format: String, _ arguments: [Any]) {

现在我在字符串扩展中使用它来为 Ints 工作

  init(format: String, _ arguments: [Any]) {
            var copy = format
            for argument in arguments {
                switch argument {
                case let replacementInt as Int:
                    String.handleInt(copy: &copy, replacement: String(replacementInt))
                default:
                    self = format
                }
            }
        self = copy
    }

private static func handleInt(copy: inout String, replacement: String) {

但由于我希望它适用于所有值,因此我尝试使用开关查找具有使用 String(value) 初始化程序转换为字符串所需的 LosslessStringConvertible 协议的 Any 类型。

     init(format: String, _ arguments: [Any]) {
        var copy = format
        for argument in arguments {
            switch argument {
            case let replacementInt as LosslessStringConvertible:
                String.handleAnyValue(copy: &copy, replacement: String(replacementInt))
            default:
                self = format
            }
        }
    self = copy
}

但是,应用 String(replacementInt) 时出现以下错误

协议类型“LosslessStringConvertible”不能符合 'LosslessStringConvertible' 因为只有具体类型才能符合 协议

奖金 如果我可以在不导入任何库并简单地使用 swift 编写的情况下做到这一点,那将是一个好处。

【问题讨论】:

  • 错误很明显。 String() 初始化器的参数必须是具体类型,而不是协议。
  • 如何创建一个具体的 Any 类型,它可以是 Int 或 String,或者根本不可能,我必须将类型转换为 Int。 @vadian
  • 为什么不是第二种情况? case let replacementInt as Intcase let replacementString as StringhandleAnyValue 中的参数replacement 可以声明为LosslessStringConvertible 或泛型T<LosslessStringConvertible>

标签: swift switch-statement protocols control-flow


【解决方案1】:

您可以使符合 LosslessStringConvertible 成为参数的要求:

init<S: LosslessStringConvertible>(format: String, _ arguments: [S])

这将支持开箱即用符合该协议的所有类型(并允许扩展其他类型以符合该协议):

var x: String  = String(format: "%i %@", 5, "five")
print(x) // prints "5 five"

此解决方案的限制是,例如不符合 LosslessStringConvertible 的类型将导致错误。例如:

class Z {}
let z = Z()
var y: String = String(format: "%i %@ %@", 5, "five", z) // Compilation error: Argument type 'Z' does not conform to expected type 'CVarArg'

【讨论】:

    猜你喜欢
    • 2017-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-01
    • 1970-01-01
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多