Tips: String 和 Data 的相互转换

当将一个 String 转换为 Data 时,返回值是可选类型 Optional的,举个例子:

1
let cafe: Data? = "Café".data(using: .utf8) // non-nil

所以强制解包这个 Optional Value 是否安全呢?或者说它有没有可能返回空值 nil?这取决于你使用的编码类型,当使用 Unicode 编码(如 utf8 或者 utf16)的时候,你可以安全地强制解包。

当使用其他字符串编码时,强制解包是不安全的(除非你确切知道该字符串保证可以用该编码表示出来),举个例子:

1
let upsideDown = "🙃".data(using: .ascii)

ASCII 不能表示 emoji,因此转换失败。这不仅限于表情符号,Unicode 可以表示比 ASCII 更多的字符。举个例子:

1
var bytes: Data = "Café".data(using: .utf8)!

当你读取一些字符串字节的时候,是不知道它是否为有效的 Unicode。最后的两个字节是字符 é,尝试删除最后一个字节:

1
2
bytes.removeLast()
String(data: bytes, encoding: .utf8) // nil

如上,字节解码失败。因此除非你确切知道数据来自于哪里,否则不能盲目解码,更不应该强制解包字符串。但是有些时候即使存在解码错误,仍要显示字符串内容的时候可以这样:

1
String(decoding: bytes, as: UTF8.self) // "Caf�"

这是 String 中的一个特殊初始化方法,如果遇到不能解码的数据,它将插入字符 � 来替换。

TLDR

  • 仅当使用 Unicode 编码时,强制解开 String -> Data 的结果数据是安全的。
  • 强制解开 Data -> String 的结果数据是不安全的。

原文地址:Swift Tip: String to Data and Back · objc.io