我正在研究如何从DispatchData实例中创建一个Data实例。我从一个静态函数开始:
static func dispatchData(fromData data: Data) -> DispatchData {
return data.withUnsafeBytes { (typedPtr: UnsafePointer<UInt8>) -> DispatchData in
let bufferPtr = UnsafeRawBufferPointer(start: UnsafeRawPointer(typedPtr), count: data.count)
return DispatchData(bytes: bufferPtr)
}
}这很好(巧合的是,它与这个答案非常相似)。然后,我决定在扩展中将其作为初始化器添加到DispatchData中,并写道:
private extension DispatchData {
init(data: Data) {
data.withUnsafeBytes { (typedPtr: UnsafePointer<UInt8>) in // 1
let bufferPtr = UnsafeRawBufferPointer(start: UnsafeRawPointer(typedPtr), count: data.count)
self.init(bytes: bufferPtr)
}
}
}在此,编译器在标记为// 1的行上犹豫不决。
初始化前由闭包捕获的变量“self.__wrapped”
这是有意义的--编译器不希望在我将self委托给init(bytes: UnsafeRawBufferPointer)之前捕获它,因为存储的变量(在本例中是__wrapped )还没有初始化。但是我找不到获得UnsafeRawBufferPointer的另一种方法;我不能从data.withUnsafeBytes返回它,按照文档
警告 字节指针参数不应在调用闭包的生存期之外存储和使用。
我知道我可以回到使用静态函数来实现我想要的,但是如果有一种方法来添加这个初始化器,我会更喜欢它。是否有办法使此初始化器按预期工作?
发布于 2017-09-28 10:09:50
扩展的问题是,尽管编译器知道将闭包作为非转义参数传递给withUnsafeBytes(_:);但它无法保证只调用一次(初始化所需的)。
一个简单的解决方案是,而不是链接到另一个初始化器,只需自己构造一个DispatchData的新实例,然后将其分配给self,从而完成初始化:
import Foundation
private extension DispatchData {
init(data: Data) {
self = data.withUnsafeBytes { (typedPtr: UnsafePointer<UInt8>) in
DispatchData(bytes:
UnsafeRawBufferPointer(start: typedPtr, count: data.count)
)
}
}
}还请注意,在将UnsafePointer<UInt8>作为参数传递给UnsafeRawPointer?时,有一个从call到UnsafeRawPointer?的隐式转换;因此,我们不需要将它封装在初始化调用中。
在Swift 5中,withUnsafeBytes直接给出一个UnsafeRawBufferPointer:
private extension DispatchData {
init(data: Data) {
self = data.withUnsafeBytes(DispatchData.init)
}
}https://stackoverflow.com/questions/46462022
复制相似问题