我知道我能做
//Setup
let originalBytes: [UInt8] = [0x0, 0x1, 0x2]
let originalData = Data(originalBytes)
//This
let getByteArFromData: [UInt8] = [UInt8](originalData)
现在,我非常确信getByteArFromData
将字节复制到新分配的内存中(我错了吗?(。
随着数据的缩放(例如图像、编解码器操作等(,这会使变得昂贵
我之所以提出这个问题,是因为我想通过一个类似数组的接口来操作数据,但据我所知,不安全的API是可行的。所以…
使用不安全的API是唯一的方法吗?这是推荐的方法吗?
我也玩过一些指针运算(只是进入了不安全的API,不确定如果我可以使用类似数组的接口,我是否应该投入时间(。
这里有一些操场代码(如果你愿意的话,请批评它并回答评论中的问题(:
import Foundation
//MARK:- Setup
final class PlaygroundSwingSet
{
//Squish unimportant setup code
private let byteAr: [UInt8]
private lazy var data: Data = {Data(byteAr)}()
init(_ bytes: [UInt8]) {self.byteAr = bytes}
func swing() -> Int
{
//Unsafe API stuff
return data.withUnsafeBytes {(dataBufferPtr) -> (Int) in //No need for [weak self], right?
//I don't like how the pointers are only valid in this closure.
//It adds an indent to my code to which my "code OCD" forces me to abstract out
self.middleOut(dataBufferPtr)
}
}
private func middleOut(_ dataBufferPtr: UnsafeRawBufferPointer) -> Int
{
//Yuck, I have to make sure count isn't 0 AND safely unwrap.
//Why is .baseAddress even optional then?
guard let dataPtr = dataBufferPtr.baseAddress?.assumingMemoryBound(to: UInt8.self), dataBufferPtr.count > 0 else {
print("data is empty")
return 0
}
let middishIndex = dataBufferPtr.count / 2 - 1
//More yuck.
print("truncated middle element's value is (dataPtr.advanced(by: middishIndex).pointee)")
print("this should yield the same thing: ((dataPtr + middishIndex).pointee)")
return middishIndex
}
}
//MARK:- Code Execution
let a = PlaygroundSwingSet([0x1, 0x2, 0x3, 0x4]).swing() //a = 1
//Console prints
/*
truncated middle element's value is 3
this should yield the same thing: 2
*/
let b = PlaygroundSwingSet([]).swing() //b = 0
//Console prints
/*
data is empty
*/
不需要强制转换Data,因为它支持下标运算符访问给定索引处的UInt8
。
顺便说一句,它还支持isEmpty
,所以您不需要检查count是否为0。
var data = Data(repeating: 0, count: 5)
data.indices.forEach { data[$0] = UInt8($0) }
print(data[2])