问题
I want to convert UInt16 to UInt8 array, but am getting the following error message:
'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.
The code:
let statusByte: UInt8 = UInt8(status)
let lenghtByte: UInt16 = UInt16(passwordBytes.count)
var bigEndian = lenghtByte.bigEndian
let bytePtr = withUnsafePointer(to: &bigEndian) {
UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: MemoryLayout.size(ofValue: bigEndian))
}
回答1:
As the error message indicates, you have to use withMemoryRebound()
to reinterpret the pointer to UInt16
as a pointer to UInt8
:
let bytes = withUnsafePointer(to: &bigEndian) {
$0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: bigEndian)) {
Array(UnsafeBufferPointer(start: $0, count: MemoryLayout.size(ofValue: bigEndian)))
}
}
The closures are invoked with pointers ($0
) which are only valid
for the lifetime of the closure and must not be passed to the outside
for later use. That's why an Array
is created and used as return value.
There is a simpler solution however:
let bytes = withUnsafeBytes(of: &bigEndian) { Array($0) }
Explanation: withUnsafeBytes
invokes the closure with a UnsafeRawBufferPointer
to the storage of the bigEndian
variable.
Since UnsafeRawBufferPointer
is a Sequence
of UInt8
, an array
can be created from that with Array($0)
.
回答2:
You can extend Numeric protocol and create a data property as follow:
Swift 4 or later
extension Numeric {
var data: Data {
var source = self
return Data(bytes: &source, count: MemoryLayout<Self>.size)
}
}
Since Swift 3 Data conforms to RandomAccessCollection
so you can just create an array of bytes from your UInt16 bigEndian data:
extension Data {
var array: [UInt8] { return Array(self) }
}
let lenghtByte = UInt16(8)
let bytePtr = lenghtByte.bigEndian.data.array // [0, 8]
来源:https://stackoverflow.com/questions/44357292/how-to-convert-uint16-to-uint8-in-swift-3