Быстрая перезапись init (формат: String, _ аргументы: CVarArg ...) - PullRequest
0 голосов
/ 23 февраля 2020

Я пытаюсь переписать стандартный метод String (формат, аргументы), найденный в фундаменте, который принимает строку и заменяет все значения, содержащие% i, на int и% @ на строки и целый ряд типов. https://developer.apple.com/documentation/swift/string/3126742-init

Поскольку я не знаю c Я преобразовал инициализатор из

init(format: String, _ arguments: CVarArg) {

в

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

Теперь я заставил его работать для Ints, используя это в String Extension

  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) {

, но так как я хотел бы, чтобы это работало для всех значений, я пытаюсь использовать переключатель для поиска типа Any, у которого есть протокол LosslessStringConvertible требуется преобразовать в строку с помощью инициализатора String (значение).

     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 (replaceInt)

типа протокола 'LosslessStringConvertible' появляется следующая ошибка не может соответствовать 'LosslessStringConvertible', поскольку только конкретные типы могут соответствовать протоколам

Бонус Бонус был бы, если бы я мог сделать это без импорта какой-либо библиотеки и простого написания с использованием swift.

1 Ответ

1 голос
/ 23 февраля 2020

Вы можете сделать соответствие 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'
...