метод subdata в Swift, кажется, не работает так, как я хочу - PullRequest
0 голосов
/ 26 апреля 2019

У меня есть следующий код на игровой площадке (Swift 5)

import Foundation

let array : [UInt8] = [0,1,2,3,4,5,6,7,8,9,10,11,12]
public extension Data {
    func uint32( offset:Int)-> UInt32{

        let range = offset..<(offset+4)
        let copy = self.subdata(in: range)

        print(copy as NSData) // Prints  <02030405>

        return copy.withUnsafeBytes{
            $0.load(fromByteOffset: 0, as: UInt32.self).bigEndian
        }
    }
}

let data = Data(array)
let datadropped = data.dropFirst(2)
print(data as NSData) // Prints <00010203 04050607 08090a0b 0c>
print(datadropped as NSData)   // Prints <02030405 06070809 0a0b0c>


let sub =  data.subdata(in: 4..<8 )  // gives 4,5,6,7
let sub2 = datadropped.subdata(in: 4..<8) // also gives 4,5,6,7

data.uint32(offset: 2)

Теперь, если я устанавливаю смещение в последней строке как 0 или 1, оно вылетает.Смещение 2 работает, но возвращает uint, построенный с использованием байтов 02,03,04,05, что не соответствует ожиданиям.В документации говорится, что dropFirst () и subdata () возвращают копии данных.

Я заставил свою функцию uint32 работать со следующим кодом.Но я хотел бы знать, почему диапазоны байтов в исходной функции не работают.Как заставить подлинную новую копию данных?Если бы кто-то мог мне это объяснить, я был бы благодарен.

extension Data
    func uint32( offset:Int)-> UInt32{
        let array = Array(0...3).map {
            uint8(offset: $0+ offset)
        }
        return array.withUnsafeBytes{
            $0.load(fromByteOffset: 0, as: UInt32.self).bigEndian
        }
    }

   func uint8( offset:Int)-> UInt8 {
        return self.withUnsafeBytes{
            $0.load(fromByteOffset: offset, as: UInt8.self).bigEndian
        }
    }
}

1 Ответ

2 голосов
/ 26 апреля 2019

datadropped - это Срез

Он содержит подмножество данных, но имеет те же индексы, что и исходная коллекция.Это происходит сбой, потому что первый индекс datadropped равен 2, а не 0.

Чтобы получить новый Data объект, вы должны написать

let datadropped = Data(data.dropFirst(2))

Для получения дополнительной информации о срезах, пожалуйста, смотрите WWDC 2018: эффективное использование коллекций (с 11:00)

Примечание. Можно сбросить параметр fromByteOffset

return copy.withUnsafeBytes{
    $0.load(as: UInt32.self).bigEndian
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...