2

Hi I am converting existing swift 2.0 code to swift 3.0 but came across an error while conversion:

Cannot invoke initializer for type 'UnsafePointer' with an argument list of type '(UnsafeRawPointer)'

Here is my code:

extension Data {

  var hexString : String {
    let buf = UnsafePointer<UInt8>(bytes) // here is the error
    let charA = UInt8(UnicodeScalar("a").value)
    let char0 = UInt8(UnicodeScalar("0").value)

    func itoh(_ i: UInt8) -> UInt8 {
        return (i > 9) ? (charA + i - 10) : (char0 + i)
    }

    let p = UnsafeMutablePointer<UInt8>.allocate(capacity: count * 2)

    for i in 0..<count {
        p[i*2] = itoh((buf[i] >> 4) & 0xF)
        p[i*2+1] = itoh(buf[i] & 0xF)
    }

    return NSString(bytesNoCopy: p, length: count*2, encoding: String.Encoding.utf8.rawValue, freeWhenDone: true)! as String
 }
}
piet.t
  • 11,718
  • 21
  • 43
  • 52
S Ilyas
  • 21
  • 3

1 Answers1

1

In Swift 3 you have to use withUnsafeBytes() to access the raw bytes of a Data value. In your case:

withUnsafeBytes { (buf: UnsafePointer<UInt8>) in
    for i in 0..<count {
        p[i*2] = itoh((buf[i] >> 4) & 0xF)
        p[i*2+1] = itoh(buf[i] & 0xF)
    }
}

Alternatively, use the fact that Data is a collection of bytes:

for (i, byte) in self.enumerated() {
    p[i*2] = itoh((byte >> 4) & 0xF)
    p[i*2+1] = itoh(byte & 0xF)
}

Note that there is another problem in your code:

NSString(..., freeWhenDone: true)

uses free() to release the memory, which means that it must be allocated with malloc().

Other (shorter, but potentially less efficient) methods to create a hex representation of a Data value can be found at How to convert Data to hex string in swift.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382