Skip to content

Instantly share code, notes, and snippets.

@brennanMKE
Last active December 16, 2023 18:30
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save brennanMKE/e37061ae41a885d6b33d19641151f609 to your computer and use it in GitHub Desktop.
Save brennanMKE/e37061ae41a885d6b33d19641151f609 to your computer and use it in GitHub Desktop.
Copy bytes from Data with Swift

Copying Bytes from Data

The Data type in Swift holds onto a raw stream of bytes. Accessing these bytes is done with the Unsafe API which provides direct access to these bytes within an instance of Data. Legacy code which uses NSData is still sometimes used because it is familiar. The copyBytes:length: function can be used to copy the bytes into an array by referencing a pointer. It is best to instead use the modern Swift API for accessing bytes.

See the included extension as well as the playground which demonstrate how the modern Swift API can be used.

Credit: sharplet

import Foundation
let size = MemoryLayout<Int16>.stride
let data = Data(bytes: [1, 0, 2, 0, 3, 0]) // little endian for 16-bit values
let int16s = data.withUnsafeBytes { (bytes: UnsafePointer<Int16>) in
Array(UnsafeBufferPointer(start: bytes, count: data.count / size))
}
let length = data.count * MemoryLayout<Int16>.stride
var bytes1 = [Int16](repeating: 0, count: data.count / size)
(data as NSData).getBytes(&bytes1, length: length)
let bytes2 = data.withUnsafeBytes {
UnsafeBufferPointer<Int16>(start: $0, count: data.count / size).map(Int16.init(littleEndian:))
}
let bytes3 = data.withUnsafeBytes {
Array(UnsafeBufferPointer<Int16>(start: $0, count: data.count / size))
}
// Expected output
// [1, 2, 3]
int16s
bytes1
bytes2
bytes3
extension Data {
func copyBytes<T>(as _: T.Type) -> [T] {
return withUnsafeBytes { (bytes: UnsafePointer<T>) in
Array(UnsafeBufferPointer(start: bytes, count: count / MemoryLayout<T>.stride))
}
}
}
@Shellback3
Copy link

The extension is deprecated for Swift 5

"'withUnsafeBytes' is deprecated: use withUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R instead"

I'm attempting to write my first Swift app and am too green to understand how to modify the extension (I thank you for it, though).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment