When converting a string into data, the return type is optional. For example:
let cafe: Data? = "Café".data(using: .utf8)
Is it safe to force-unwrap this value? Can it ever return
? It depends. When you use a Unicode encoding (such as
), you can safely force-unwrap. Strings in Swift use Unicode internally, so encoding a string using a Unicode encoding will always succeed.
When you use other encodings, it is not
safe to force-unwrap (unless you explicitly know that a string is guaranteed to be representable). It is easy to see this with an example:
let upsideDown = "🙃".data(using: .ascii)
ASCII can't represent emoji, and the conversion will fail. This isn't limited to emoji, Unicode can represent vastly more characters than ASCII.
How about the other way around? When we want to convert data into a string, can we be sure it's safe to force-unwrap? In this case, the answer is an unqualified no
. Converting data into a string can always fail.
For example, here are the bytes for the
var bytes: Data = cafe!
When you read some bytes, you never know if it's valid Unicode. The last two bytes are the mark on top of the "é" and the "e". We can try to remove the "e" from the array, so that the mark has no character left to modify:
String(data: bytes, encoding: .utf8)
As we can see, decoding fails. Unless you know exactly where the data comes from, you shouldn't rely on decoding to succeed, and you shouldn't force-unwrap the string. Sometimes, however, you might want to display what is in the string, even if there are decoding errors. There is a special initializer for this, which will try to repair the data, and inserts the "�" character (a replacement character
) if it can't decode the data.
String(decoding: bytes, as: UTF8.self)
To learn more about Swift's strings in depth, check out our book, Advanced Swift