Edit, updated my answer for two things:
- Not returning the pointer from withUnsafeBytes
- Accounting for Swift 5' deprecation warning: 'withUnsafeBytes' is deprecated: use
withUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R
instead
// buffer pointer captured is converted to byte pointer which is used in the block to decode the base64 encoded Data
encodedStringData.withUnsafeMutableBytes { (rawBufferPtr: UnsafeMutableRawBufferPointer) in
if let rawPtr = rawBufferPtr.baseAddress {
let decodedString = String(bytesNoCopy: rawPtr, length: rawBufferPtr.count, encoding: .utf8, freeWhenDone: false)
print(decodedString!)
}
}
someData.withUnsafeBytes { (bufferRawPtr: UnsafeRawBufferPointer) in
// For converting an UnsafeRawBufferPointer to its typed variant, in this case UnsafeBufferPointer<UInt8>
let bufferTypedPtr = bufferRawPtr.bindMemory(to: UInt8.self)
// Then, getting the typed UnsafePointer, in this case UnsafePointer<UInt8>
let unsafePointer = bufferTypedPtr.baseAddress!
}
Note: Swift 5 doesn't allow you to access encodedStringData
from within the withUnsafeMutableBytes
block! Read Swift 5 Exclusivity Enforcement for why
.
Capturing the pointer outside of the block is apparently not recommended, it works but the behavior can get to be undefined in the future
Old answer:
This will help someone looking for getting to the underlying raw bytes (in a UnsafeMutablePointer<UInt8>
representation) of a Data
object as a variable for further use (instead of having to write all of the logic in the withUnsafeMutableBytes
block).
var encodedStringData = Data(base64Encoded: "Vmlub2QgaXMgZ3JlYXQh")!
// byte pointer variable used later to decode the base64 encoded Data
let rawPtr: UnsafeMutablePointer<UInt8> = encodedStringData.withUnsafeMutableBytes { (bytePtr: UnsafeMutablePointer<UInt8>) in bytePtr }
let decodedString = String(bytesNoCopy: rawPtr, length: encodedStringData.count, encoding: .utf8, freeWhenDone: false)
print(decodedString, encodedStringData)