如何在Swift 3中将UInt16转换为UInt8?

Joh*_*cke 1 type-conversion uint16 swift uint8array

我想将UInt16转换为UInt8数组,但收到以下错误消息:

'init'不可用:使用'withMemoryRebound(to:capacity:_)'临时查看内存作为另一种布局兼容类型.

代码:

    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))
    }
Run Code Online (Sandbox Code Playgroud)

Mar*_*n R 7

如错误消息所示,您必须使用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)))
    }
}
Run Code Online (Sandbox Code Playgroud)

使用指针($0)调用闭包,指针仅在闭包的生命周期内有效,不得传递给外部供以后使用.这就是为什么Array创建并用作返回值的原因.

但是有一个更简单的解决方案:

let bytes = withUnsafeBytes(of: &bigEndian) { Array($0) }
Run Code Online (Sandbox Code Playgroud)

说明: withUnsafeBytes使用a调用闭包UnsafeRawBufferPointer来存储bigEndian变量.由于UnsafeRawBufferPointer是一个SequenceUInt8,阵列可以从与创建的Array($0).


Leo*_*bus 6

您可以扩展 Numeric 协议并创建一个数据属性,如下所示:

Swift 4 或更高版本

extension Numeric {
    var data: Data {
        var source = self
        return Data(bytes: &source, count: MemoryLayout<Self>.size)
    }
}
Run Code Online (Sandbox Code Playgroud)

由于 Swift 3 Data 符合,RandomAccessCollection因此您可以从 UInt16 bigEndian 数据创建一个字节数组:

extension Data {
    var array: [UInt8] { return Array(self) }
}
Run Code Online (Sandbox Code Playgroud)
let lenghtByte = UInt16(8)
let bytePtr = lenghtByte.bigEndian.data.array   // [0, 8]
Run Code Online (Sandbox Code Playgroud)