我在操场上有以下代码(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
}
}
}
答案 0 :(得分:2)
datadropped
是Slice
它包含数据的子集,但与原始集合共享相同的索引。由于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
}