In Swift, hex usually rides on Data: parse hex text into bytes, then decode with String(data:encoding:) when the payload is text. The reverse path is Data → hex for logs, BLE, and hashes.
Concepts: hex encoding overview. Quick check: Hex to String.
Data → hex string
import Foundation
extension Data {
var hexString: String {
map { String(format: "%02x", $0) }.joined()
}
}
let data = "Hello".data(using: .utf8)!
print(data.hexString) // 48656c6c6f
Hex string → Data
extension Data {
init?(hexString: String) {
let cleaned = hexString
.replacingOccurrences(of: " ", with: "")
.replacingOccurrences(of: "0x", with: "")
guard cleaned.count % 2 == 0 else { return nil }
var bytes = [UInt8]()
bytes.reserveCapacity(cleaned.count / 2)
var index = cleaned.startIndex
while index < cleaned.endIndex {
let next = cleaned.index(index, offsetBy: 2)
let byteStr = cleaned[index..<next]
guard let byte = UInt8(byteStr, radix: 16) else { return nil }
bytes.append(byte)
index = next
}
self.init(bytes)
}
}
if let data = Data(hexString: "e4bda0e5a5bd"),
let text = String(data: data, encoding: .utf8) {
print(text) // 你好
}
Hex → String helper
func string(fromHex hex: String, encoding: String.Encoding = .utf8) -> String? {
guard let data = Data(hexString: hex) else { return nil }
return String(data: data, encoding: encoding)
}
Common iOS/macOS uses
- Displaying SHA-256 digests from CryptoKit as hex.
- BLE characteristic values arriving as
Data. - Debugging API payloads that embed binary fields as hex text.
Pitfalls
- Odd-length hex → fail (
nil), do not invent padding. - Wrong
String.Encoding→nilor mojibake; prefer.utf8unless a protocol says otherwise. - Not every
Datais text — keep binary asDatawhen it is a key, nonce, or file blob.
Related: JavaScript · Python · String to Hex tool.