2

I am migrating a project to Swift 4 and I cannot figure out how I am supposed to use the new API:s to do this in Swift 4. The following code is the old Swift 3 way (from the middle of a function hence the guard):

let formattedString = "A string"
guard let stringData: Data = formattedString.data(using: .utf8) else { return }
let data: DispatchData = [UInt8](stringData).withUnsafeBufferPointer { (bufferPointer) in
    return DispatchData(bytes: bufferPointer)
}

Now it gives the following warning: init(bytes:)' is deprecated: Use init(bytes: UnsafeRawBufferPointer) instead

In order to do that you need to get access to a variable with the type UnsafeRawBufferPointer instead of UnsafeBufferPointer<UInt8>

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
Alex
  • 731
  • 1
  • 11
  • 24

2 Answers2

4

Use withUnsafeBytes to get an UnsafeRawPointer to the data bytes, create an UnsafeRawBufferPointer from that pointer and the count, and pass it to the DispatchData constructor:

let formattedString = "A string"
let stringData = formattedString.data(using: .utf8)! // Cannot fail!

let data = stringData.withUnsafeBytes {
    DispatchData(bytes: UnsafeRawBufferPointer(start: $0, count: stringData.count))
}

Alternatively, create an array from the Strings UTF-8 view and use withUnsafeBytes to get an UnsafeRawBufferPointer representing the arrays contiguous element storage:

let formattedString = "A string"
let data = Array(formattedString.utf8).withUnsafeBytes {
    DispatchData(bytes: $0)
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Can `formattedString.data(using: .utf8)!` fail with some other string? The string in my project is not a literal. Just posted it that way to make the code shorter. – Alex Sep 21 '17 at 14:47
  • @Alex: No. Compare https://stackoverflow.com/questions/46152617/can-the-conversion-of-a-string-to-data-with-utf-8-encoding-ever-fail. – Martin R Sep 21 '17 at 14:48
  • OK, nice to know. Also your code seems to give the same deprecation warning. But that is expected since we initialize the type `UnsafeBufferPointer`, we need something of type `UnsafeBufferPointer`. – Alex Sep 21 '17 at 14:51
  • @Alex: That is strange. The code compiles and runs without warnings in my Xcode 9.0 (9A235). – Martin R Sep 21 '17 at 14:52
  • Site says: Error communicating with database. Snapshot not loaded. – Alex Sep 21 '17 at 15:02
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/155011/discussion-between-martin-r-and-alex). – Martin R Sep 21 '17 at 15:03
0

All solutions above look over complicated, it's actually much simpler:

let string = "str"
if let data = string.data(using: .utf8) {
  let dispatchData = data.withUnsafeBytes { DispatchData(bytes: $0) }
}
pronebird
  • 12,068
  • 5
  • 54
  • 82