I'm trying to rewrite the standard String(format, arguments) method found in foundation which takes a string and replaces all values containing %i with ints and %@ with strings and a whole range of types. https://developer.apple.com/documentation/swift/string/3126742-init
Since I don't know c I converted the initializer from
init(format: String, _ arguments: CVarArg) {
to
init(format: String, _ arguments: [Any]) {
Now I got it working for Ints using this in a String Extension
init(format: String, _ arguments: [Any]) {
var copy = format
for argument in arguments {
switch argument {
case let replacementInt as Int:
String.handleInt(copy: ©, replacement: String(replacementInt))
default:
self = format
}
}
self = copy
}
private static func handleInt(copy: inout String, replacement: String) {
but since I would like this to work for all values I'm trying to use the switch to look for type Any that has the Protocol of LosslessStringConvertible required to convert to a string using the String(value) initializer.
init(format: String, _ arguments: [Any]) {
var copy = format
for argument in arguments {
switch argument {
case let replacementInt as LosslessStringConvertible:
String.handleAnyValue(copy: ©, replacement: String(replacementInt))
default:
self = format
}
}
self = copy
}
However, I get the following error when applying String(replacementInt)
Protocol type 'LosslessStringConvertible' cannot conform to 'LosslessStringConvertible' because only concrete types can conform to protocols
Bonus A bonus would be if I could do this without importing any library and simply writing using swift.
You could make conformance to LosslessStringConvertible
to be a requirement for arguments:
init<S: LosslessStringConvertible>(format: String, _ arguments: [S])
This would support all types that conform that protocol out of the box (and allows to extend other types to conform this protocol):
var x: String = String(format: "%i %@", 5, "five")
print(x) // prints "5 five"
Limitation with this solution is that for instance type that doesn't conform to LosslessStringConvertible will cause an error. For example:
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'