根据Swift 3中Data的文档,我可以使用一个初始化程序从UnsafeRawPointer创建数据。实际上我需要的是相反的。我有一个数据,我想创建一个指向数据字节的UnsafeRawPointer。这就是我现在正在做的事情:
1. let data = <from some where>
2. let unsafePointer = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count)
3. unsafePointer.initialize(to: 0, count: data.count) // is this necessary?
4. data.copyBytes(to: unsafePointer, count: data.count)
5. let unsafeRawPointer = unsafePointer.deinitialize() // this is of the type UnsafeMutalbleRawPointer, and I can use it where UnsafeRawPointer is needed.
我确认此代码适用于Xcode Playground。代码甚至可以在没有第3行的情况下工作。我不确定该行与否有什么区别。无论如何,我的问题是,我做得对吗?有没有更简单的方法呢?
答案 0 :(得分:28)
withUnsafeBytes()
给你一个指向字节的(类型)指针,
这可以转换为原始指针:
let data = <Data from somewhere>
data.withUnsafeBytes { (u8Ptr: UnsafePointer<UInt8>) in
let rawPtr = UnsafeRawPointer(u8Ptr)
// ... use `rawPtr` ...
}
指针仅在调用的生命周期内有效 闭合。
或者,您可以桥接到NSData
并访问原始字节:
let nsData = data as NSData
let rawPtr = nsData.bytes
现在指针在nsData
有效的同一范围内有效。
从 Swift 5 开始
let data = <Data from somewhere>
data.withUnsafeBytes { rawBufferPointer in
let rawPtr = rawBufferPointer.baseAddress!
// ... use `rawPtr` ...
}
因为closure参数现在是UnsafeRawBufferPointer
。
答案 1 :(得分:6)
我们找不到从UnsafeRawPointer
检索Data
的方法或属性。
所以,替代方案: func withUnsafeBytes((UnsafePointer) -> ResultType)
你可以这样写:
let data: Data = <initialize it as you like>
data.withUnsafeBytes {(uint8Ptr: UnsafePointer<UInt8>) in
let rawPtr = UnsafeRawPointer(uint8Ptr)
//`rawPtr` (and `uint8Ptr`) is guaranteed to be valid in this closure
//...
//You have no need manage `rawPtr`.
}
(哦,这与Martin R的答案的前半部分相同。)
但是,如果您希望UnsafeRawPointer
有效期的时间长于关闭时间,则需要复制Data
的内容:
例如:
let uint8Ptr = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count)
uint8Ptr.initialize(from: data) //<-copying the data
//You need to keep `uint8Ptr` and `data.count` for future management
let uint8PtrCount = data.count
//You can convert it to `UnsafeRawPointer`
let rawPtr = UnsafeRawPointer(uint8Ptr)
//Use `rawPtr` while `uint8Ptr` is valid
//...
//Deinitialize and deallocate the region
uint8Ptr.deinitialize(count: uint8PtrCount)
uint8Ptr.deallocate(capacity: uint8PtrCount)
(您可以将UnsafeMutableRawPointer
作为deinitialize(count:)
的返回值,但该区域处于未初始化状态,因此您不应访问该区域。)
答案 2 :(得分:1)
在Swift 5中:
'withUnsafeBytes' is deprecated: use `withUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R` instead
可能的解决方法是:
buffer.withUnsafeBytes{ (bufferRawBufferPointer) -> Void in
let bufferPointer: UnsafePointer<UInt8> = bufferRawBufferPointer.baseAddress!.assumingMemoryBound(to: UInt8.self)
let rawPtr = UnsafeRawPointer(bufferPointer)
//USE THE rawPtr
}