Swift中的subdata方法似乎并没有按照我的意愿进行

时间:2019-04-26 16:34:08

标签: swift

我在操场上有以下代码(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的作品,但返回使用字节02,03,04,05构造的uint,这不是我期望的。该文档指出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 个答案:

答案 0 :(得分:2)

datadroppedSlice

它包含数据的子集,但与原始集合共享相同的索引。由于datadropped的第一个索引为2,而不是0,因此崩溃。

要获取新的Data对象,您必须编写

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

有关切片的更多信息,请观看WWDC 2018: Using Collections Effectively(从11:00开始)

注意:您可以删除fromByteOffset参数

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