How to use Data withUnsafeMutableBytes in Swift 3

I had Xcode 8 convert my code to Swift 3. It changed all occruances of NSData to Data. In my Swift 2 code I had:


var data : NSData

var bytes = data.bytes


In Swift 3 I believe that I should be using withUnsafeMutbaleBytes and my code should looks somehting like:


var data : Data

var bytes = data.withUnsafeMutableBytes { (<#UnsafeMutablePointer<ContentType>#>) -> ResultType in

<#code#>

}


There isn't much documentation yet and I can't figure out how to properly use withUnsafeMutableBytes. Are there any examples of how to use withUnsafeMutableBytes?

Accepted Reply

Basic usage of `withUnsafeBytes` and `withUnsafeMutableBytes`.


import UIKit
var str = "Hello, playground"
let data1 = str.data(using: String.Encoding.utf8)!
data1.withUnsafeBytes {(bytes: UnsafePointer<CChar>)->Void in
    //Use `bytes` inside this closure
    //...
}
var data2 = Data(capacity: 1024)!
data2.withUnsafeMutableBytes {(bytes: UnsafeMutablePointer<UInt8>)->Void in
    //Use `bytes` inside this closure
    //...
}


If you want to work with beta software, you need to work with incomplete documetation and no example codes.

You need to "infer" the usage from other similar name methods.

Replies

Basic usage of `withUnsafeBytes` and `withUnsafeMutableBytes`.


import UIKit
var str = "Hello, playground"
let data1 = str.data(using: String.Encoding.utf8)!
data1.withUnsafeBytes {(bytes: UnsafePointer<CChar>)->Void in
    //Use `bytes` inside this closure
    //...
}
var data2 = Data(capacity: 1024)!
data2.withUnsafeMutableBytes {(bytes: UnsafeMutablePointer<UInt8>)->Void in
    //Use `bytes` inside this closure
    //...
}


If you want to work with beta software, you need to work with incomplete documetation and no example codes.

You need to "infer" the usage from other similar name methods.

I used to do much more work with the withUnsafeMutablesBytes API myself. But after converting to Swift 3 and fully embracing the new Data type, I've not found much need for it.


What specifically are you needing to do? You may find that directly reading/writing/comparing as follows may be sufficient:


var theData = Data(bytes: [0x01, 0x02, 0x03])
let theValue = theData[2]     // 0x02
theData[2] = 0xFF
let theNewValue = theData[2]  // 0xFF

let theIsEqualFlag = (theData == Data(bytes: [0x01, 0x02, 0xFF])) // true

Thanks! I've developed macOS and iOS code for close to 20 years and used a lot of beta software with and without documentaiton, but I was having difficulty with this syntax in Swift. Thanks again.

Thanks. This is code that accesses the CommonCrypto framework. Now you have me thinking that there might be a simpler way to do this because Swift has evolved since I first wrote the code.

Just want to point out that `withUnsafeBytes` is a throwing function and actually needs a `try` in front of it. But this was very helpful for me. Thanks!

let transmission = packet.contents
try transmission.withUnsafeBytes { (unsafePointer: UnsafePointer<UInt8>) in
    let written = write(unsafePointer, maxLength: transmission.count)
           
    if written != transmission.count {
        throw Error.unableToWriteAllBytes
    }
}

Just want to point out that

withUnsafeBytes
is a throwing function and actually needs a
try
in front of it.

Just FYI, it’s actually a

rethrow
function, which means that it throws if the block you pass it throws. Which is pretty cool. You can learn more in the Rethrowing Functions and Methods section of The Swift Programming Language

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"