In Swift, how does one assign Data to array of UInt32?

北城余情 提交于 2020-03-04 16:30:27

问题


I have Swift code which reads a binary file representing a sequence of UInt32 values like this:

let fileData = binaryFile.readData(ofLength: 44)

guard fileData.count > 0 else { break }

let headerData = fileData.withUnsafeBytes {
    Array(UnsafeBufferPointer<UInt32>(start: $0, count: 11))
}

let polyCount = headerData[1].bigEndian
let polyFlags = headerData[2].bigEndian

I'd not used the program containing this code for a while, but when returning to it recently, it still works as expected, but now gives a deprecation warning:

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

I've searched for quite a long time for an un-deprecated way to do this without success. There are many examples across the web (including in stackoverflow) but almost all of them written before this deprecation into effect. Frankly, I've fried my brain hunting and trying suggestions! I am prepared to accept that I'm missing something totally obvious ("If it's getting complicated, you're doing it wrong."), but I work in an environment where I have no colleagues to ask .. except here.

Any guidance would be much appreciated.


回答1:


RamsayCons's own solution is nice, but what about the performance? I think, it could be better if we reduce all unnecessary operation.

extension Data {
    func toArray<T>(type: T.Type) -> [T] where T: ExpressibleByIntegerLiteral {
        Array(unsafeUninitializedCapacity: self.count/MemoryLayout<T>.stride) { (buffer, i) in
            i = copyBytes(to: buffer) / MemoryLayout<T>.stride
        }
    }
}

measured performance gain depends, but number of execution per second is at least doubled. Bigger the data, bigger advantage!




回答2:


self.dataArray = data.withUnsafeBytes{ Array($0.bindMemory(to: UInt32.self))}



回答3:


Well, letting some time pass restored brain function! I found an answer (in stackoverflow, of course):

round trip Swift number types to/from Data

some way into that question/answer is:

extension Data {
    func toArray<T>(type: T.Type) -> [T] where T: ExpressibleByIntegerLiteral {
        var array = Array<T>(repeating: 0, count: self.count/MemoryLayout<T>.stride)
        _ = array.withUnsafeMutableBytes { copyBytes(to: $0) }
        return array
    }
}

The trick is that Arrays are not necessarily stored in contiguous memory so simply copying enough bytes in order to the destination doesn't do it. I hope this helps the next person hunting with a fried brain!!



来源:https://stackoverflow.com/questions/60067594/in-swift-how-does-one-assign-data-to-array-of-uint32

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!