我的应用程序使用某种复杂的不可变数据结构,该结构以二进制文件编码。我需要在字节级别访问它,避免任何复制。通常,我将使用C或C ++指针算术和类型转换来访问和解释原始字节值。我想对Swift做同样的事情。
我发现以下作品:
class RawData { var data: NSData! init(rawData: NSData) { data = rawData } func read<T>(byteLocation: Int) -> T { let bytes = data.subdataWithRange(NSMakeRange(byteLocation, sizeof(T))).bytes return UnsafePointer<T>(bytes).memory } func example_ReadAnIntAtByteLocation5() -> Int { return read(5) as Int } }
但是,我不确定它的效率如何。每次我调用对象时都要做data.subdataWithRange和NSMakeRange分配对象,或者它们只是用于处理指针的语法糖吗?
data.subdataWithRange
NSMakeRange
在Swift中有更好的方法吗?
编辑:
我创建了一个小的Objective-C类,该类只封装了一个将指针偏移给定字节数的函数:
@implementation RawDataOffsetPointer inline void* offsetPointer(void* ptr, int bytes){ return (char*)ptr + bytes; } @end
如果我在桥接标题中包含此类,则可以将read方法更改为
read
func read<T>(byteLocation: Int) -> T { let ptr = offsetPointer(data.bytes, CInt(byteLocation)) return UnsafePointer<T>(ptr).memory }
这不会从我的缓冲区复制数据,也不会分配其他对象。
但是,如果可能的话,从Swift执行一些指针算术仍然是很好的。
如果您只想直接UnsafePointer<T>进行操作,可以进行算术操作:
UnsafePointer<T>
let oldPointer = UnsafePointer<()> let newPointer = oldPointer + 10
您也可以像这样投射一个指针(UnsafePointer<()>等效于void *)
UnsafePointer<()>
void *
let castPointer = UnsafePointer<MyStruct>(oldPointer)