Swift中NSKeyedUnarchiver在字符串转数据后解归档失败问题排查
问题原因与解决方案
这个问题的核心在于直接用UTF-8编码把二进制归档数据转成String是完全不可行的,具体原因如下:
- NSKeyedArchiver生成的
Data是纯二进制格式,里面包含大量不符合UTF-8编码规范的字节序列。UTF-8是用来表示文本字符的编码,它对字节序列有严格的规则,当遇到非法字节时,Swift的String(decoding:as:)会自动把这些非法字节替换成Unicode的替换字符(�)——这一步已经不可逆地损坏了原始的归档数据。 - 当你再用
stringData.data(using: .utf8)把字符串转回Data时,那些被替换的字节已经无法恢复成原来的二进制内容,自然无法被NSKeyedUnarchiver正确解析。
正确的解决方式:使用Base64编码
Base64是专门设计用来将二进制数据转换为可安全存储/传输的字符串的编码方式,它会把所有二进制字节映射到64个可打印的ASCII字符,完全不会丢失或修改原始数据。
修正后的代码如下:
do { // 归档为Data,再转成Base64字符串 let data = try NSKeyedArchiver.archivedData(withRootObject: drawItems, requiringSecureCoding: false) let base64String = data.base64EncodedString() print("HERE successfully converted to a Base64 string: ", base64String) // 将Base64字符串转回Data,再解归档 if let restoredData = Data(base64Encoded: base64String), let allItems = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(restoredData) as? [DrawItem] { print("HERE items: ", allItems) } else { print("HERE FAILED to unarchive") } } catch { print("Failed: ", error) }
这样处理后,二进制数据就能在Data和String之间无损转换,后端存储Base64字符串也完全没有问题。
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

