如何将iOS设备令牌字符串转换回Data格式?
将APNs设备令牌字符串转回原始Data格式
你之前把APNs设备令牌(Data类型)转成十六进制字符串的方式是对的,但用Data(tokenString.utf8)转回的方法完全错误——因为这是把字符串里每个字符的UTF-8编码转成了Data,和原始的设备令牌字节完全不匹配。
正确的做法是把十六进制字符串每两个字符一组,解析成对应的8位字节(UInt8),再拼接成Data。下面是实现代码:
扩展String实现转换
extension String { func toAPNsDeviceTokenData() -> Data? { // 先清理字符串:转小写并移除可能存在的空格(兼容某些格式的令牌字符串) let cleanedToken = self.lowercased().replacingOccurrences(of: " ", with: "") // 十六进制字符串长度必须是偶数,否则无法完整解析每个字节 guard cleanedToken.count % 2 == 0 else { return nil } var tokenData = Data() var currentIndex = cleanedToken.startIndex while currentIndex < cleanedToken.endIndex { // 截取两个字符作为一组 let nextIndex = cleanedToken.index(currentIndex, offsetBy: 2) let byteString = cleanedToken[currentIndex..<nextIndex] // 将十六进制字符串转成UInt8字节 guard let byte = UInt8(byteString, radix: 16) else { return nil } tokenData.append(byte) currentIndex = nextIndex } return tokenData } }
使用示例
let savedTokenString = "cd414ecaf22687b31b602cec11c7c4d797ead5cfece5fc59321e7ac35e36d4c1" if let restoredTokenData = savedTokenString.toAPNsDeviceTokenData() { // 验证转换是否正确:转回字符串应该和原字符串一致 let convertedBackToString = restoredTokenData.map { String(format: "%02.2hhx", $0) }.joined() print(convertedBackToString == savedTokenString.lowercased()) // 输出 true,说明转换正确 }
为什么你的原有方法不对?
你之前用Data(tokenString.utf8)得到的Data,其实是把字符串里每个字符的UTF-8编码存成了字节。比如原字符串里的"cd",会被转成0x63('c'的ASCII码)和0x64('d'的ASCII码)两个字节,所以转回十六进制字符串后就变成了"6364",这和原始设备令牌的字节完全无关,自然不符合SDK的要求。
内容的提问来源于stack exchange,提问作者oBo
相关产品推荐
相关产品推荐

