Я знаю, что могу сделать
//Setup
let originalBytes: [UInt8] = [0x0, 0x1, 0x2]
let originalData = Data(originalBytes)
//This
let getByteArFromData: [UInt8] = [UInt8](originalData)
Теперь я симпатичен уверен, что getByteArFromData
КОПИРУЕТ байты в новую выделенную память (я здесь не прав?).
Это получает дорого по мере масштабирования данных (например, изображения, код c манипулирование и т. Д. c.).
Я мотивирован задать этот вопрос, потому что я хотел бы манипулировать данными через массивоподобный интерфейс, но, насколько мне известно, Unsafe API - это путь к go. Итак ...
Является ли использование Unsafe API единственным способом сделать это? Это рекомендуемый способ сделать это?
Я также играл с некоторой арифметикой указателей c (просто попадаю в небезопасный 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
*/