I need to convert an Integer value to String. I made a variable with an Integer value and then I have printed that using print. What is the different between the below approaches?
var word = "Count is "
var count = 100
print(word+String(describing: count)); // Count is 100
print(word+String(count)); // Count is 100
Your question is actually unnecessary because if all you want to do here is print, you can just do it directly:
print("Count is", count) // Count is 100
That's because print takes a variadic parameter and inserts space as the default separator.
However, let's answer the question anyway.
It's the difference between coercion and representation.
Coercion. Certain types can be changed into certain other types. You can change a Double to an Int and an Int to a Double. You can change an Int to a String and a String (maybe) to an Int. This is possible because the second type has an initializer whose parameter is the first type. This is something you would do in your actual program, like this:
let sum : Int = x + y
self.myLabel.text = "Your total is \(String(sum))"
Representation. For debugging purposes, all types can benefit from being representable as a string. Suppose you have a Person type. You can't change a Person to a String and vice versa — that makes no sense — but you would surely like to be able to print a Person to the console to see if you are getting the right results. This is possible because the Person type itself supplies a printable description. This is something you would do for debugging purposes:
let p = Person(first:"Matt", last:"Neuburg")
print("p is \(String(describing:p))")
Comment 1. This distinction is fairly new in Swift. It used to be that String(...) was used to express both notions. But the powers that be realized that that was a confusing conflation of the two distinct mechanisms. So nowadays, an attempt to write String(p) will fail, whereas earlier it would have succeeded. String has no Person initializer, so String(p) is forbidden; you now have to say explicitly that you are describing, not coercing.
Comment 2. The need to print a description is so obviously common that you do not have to pass thru String(describing:) if all you want to do is log the object itself. You can write print(p), because this is a shorthand for print(String(describing:p)). Similarly, string interpolation calls String(describing:) for you, so you can write print("p is \(p)"). And, as I said at the outset, print takes a variadic parameter and inserts space as the default separator, so you can write print("p is", p).
Reading the docs might help!
Here's an excerpt from String.init(describing:)
Use this initializer to convert an instance of any type to its preferred representation as a String instance. The initializer creates the string representation of
instancein one of the following ways, depending on its protocol conformance:
- If instance conforms to the
TextOutputStreamableprotocol, the result is obtained by callinginstance.write(to: s)on an empty string s.- If instance conforms to the
CustomStringConvertibleprotocol, the result isinstance.description.- If instance conforms to the
CustomDebugStringConvertibleprotocol, the result isinstance.debugDescription.- An unspecified result is supplied automatically by the Swift standard library.
Int conforms to CustomStringConvertible, so String(describing: someInt) is the same as someInt.description.
Now let's look at String(someInt), this calls this initializer:
public init<T>(_ value: T) where T : LosslessStringConvertible
Int also conforms to LosslessStringConvertible. In fact, LosslessStringConvertible inherits from CustomStringConvertible. LosslessStringConvertible specifies only one requirement - an initializer that takes a string.
The docs for init<T>(_:) says this:
Creates an instance from the description of a given
LosslessStringConvertibleinstance.
Even though description is not in a monospace font, I am quite sure (though not 100%) that this refers to the description property of CustomStringConvertible.
Assuming that init<T>(_:) indeed returns the description, String(describing: someInt) always returns the same value as String(someInt).
Note that this does not hold true for all types. It only holds true for types that conforms to LosslessStringConvertible but not TextOutputStreamable. If you have a type that conforms to both, results can be different:
struct A: TextOutputStreamable, LosslessStringConvertible {
init?(_ description: String) { }
init() { }
var description: String {
return "foo"
}
func write<Target>(to target: inout Target) where Target : TextOutputStream {
target.write("bar")
}
}
String(describing: A()) // bar
String(A()) // foo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With