Как конвертировать UInt16 в UInt8 в Swift 3?
Я хочу преобразовать UInt16 в массив UInt8, но получаю следующее сообщение об ошибке:
'init' недоступен: используйте 'withMemoryRebound(to:acity:_)', чтобы временно просмотреть память как другой тип, совместимый с макетом.
Код:
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))
}
2 ответа
Как указывает сообщение об ошибке, вы должны использовать withMemoryRebound()
переосмыслить указатель на UInt16
как указатель на 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)))
}
}
Закрытия вызываются с помощью указателей ($0
), которые действительны только в течение срока службы затвора и не должны передаваться наружу для последующего использования. Вот почему Array
создается и используется как возвращаемое значение.
Однако есть более простое решение:
let bytes = withUnsafeBytes(of: &bigEndian) { Array($0) }
Объяснение: withUnsafeBytes
вызывает закрытие с UnsafeRawBufferPointer
на хранение bigEndian
переменная. поскольку UnsafeRawBufferPointer
это Sequence
из UInt8
из этого можно создать массив Array($0)
,
Вы можете расширить числовой протокол и создать свойство данных следующим образом:
Swift 4 или позже
extension Numeric {
var data: Data {
var source = self
return Data(bytes: &source, count: MemoryLayout<Self>.size)
}
}
Поскольку Swift 3 Data соответствует RandomAccessCollection
так что вы можете просто создать массив байтов из ваших данных bigIndian UInt16:
extension Data {
var array: [UInt8] { return Array(self) }
}
let lenghtByte = UInt16(8)
let bytePtr = lenghtByte.bigEndian.data.array // [0, 8]