В Swift, как можно назначить данные массиву UInt32? - PullRequest
0 голосов
/ 05 февраля 2020

У меня есть код Swift, который читает двоичный файл, представляющий последовательность значений UInt32, например:

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

Я бы некоторое время не использовал программу, содержащую этот код, но когда возвращался к ней недавно , он все еще работает, как и ожидалось, но теперь выдает предупреждение об устаревании:

"withUnsafeBytes устарело: используйте withUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R вместо"

Я довольно долго искал Неослабный способ сделать это без успеха. В сети есть много примеров (в том числе в stackoverflow), но почти все они написаны до того, как это устарело. Честно говоря, я зажарил свой мозг на охоте и пробовал делать предложения! Я готов признать, что мне не хватает чего-то совершенно очевидного («Если это становится сложным, вы делаете это неправильно»), но я работаю в среде, где у меня нет коллег, чтобы спросить… кроме как здесь.

Любое руководство будет высоко ценится.

Ответы [ 3 ]

1 голос
/ 07 февраля 2020

Хорошее решение RamsayCons, но как насчет производительности? Я думаю, было бы лучше, если бы мы сократили все ненужные операции.

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
        }
    }
}

Измеренный прирост производительности зависит, но количество выполнений в секунду как минимум удваивается. Чем больше данных, тем больше преимущество!

1 голос
/ 08 февраля 2020
self.dataArray = data.withUnsafeBytes{ Array($0.bindMemory(to: UInt32.self))}
0 голосов
/ 05 февраля 2020

Ну, пусть пройдет некоторое время, восстановится функция мозга! Я нашел ответ (в stackoverflow, конечно же):

туда-обратно Типы чисел Swift в / из данных

как-то в этом вопросе / ответе:

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
    }
}

Хитрость заключается в том, что массивы не обязательно хранятся в непрерывной памяти, поэтому простое копирование достаточного количества байтов для того, чтобы пункт назначения не сделал этого. Я надеюсь, что это поможет следующему человеку охота с жареным мозгом !!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...