以下是我使用的示例代码:
class Dummy {
let uuid = UUID()
}
func test() {
let dummy = Dummy()
let unmangedOpaquePointer = Unmanaged.passUnretained(dummy).toOpaque()
let fromWithUnsafeAPIPointer = withUnsafePointer(to: dummy, { UnsafeMutableRawPointer(mutating: $0) })
print(unmangedOpaquePointer == fromWithUnsafeAPIPointer) // false
let dummy1 = Unmanaged<Dummy>.fromOpaque(unmangedOpaquePointer).takeUnretainedValue()
let dummy2 = fromWithUnsafeAPIPointer.assumingMemoryBound(to: Dummy.self).pointee
let dummy3 = Unmanaged<Dummy>.fromOpaque(fromWithUnsafeAPIPointer).takeUnretainedValue()
let dummy4 = unmangedOpaquePointer.assumingMemoryBound(to: Dummy.self).pointee
print(dummy1 === dummy2) // true
print(dummy1 === dummy3) // EXC_BAD_ACCESS
print(dummy2 === dummy4) // EXC_BAD_ACCESS
}
test()
- 不同的UnsafeMutableRawPointer实例
print(unmangedOpaquePointer == fromWithUnsafeAPIPointer) // false
上述代码片段的结果为"假".这是意料之中的.unmangedOpaquePointer和fromWithUnsafeAPIPointer是UnsafeMutableRawPointer
的不同实例,因此它们不相等.
然而,它们在这里都指向相同的对象dummy.如果unmangedOpaquePointer == fromWithUnsafeAPIPointer
不是实现这个事实的正确方法,我该如何测试这个事实呢?
- API调用应该配对吗?为什么?从
Unmanaged
个API返回的UnsafeMutableRawPointer和withUnsafePointer
个API之间有什么区别?
print(dummy1 === dummy2) // true
print
调用表明从两个指针检索到的dummy 1和dummy 2相同(相同的对象实例).然而,dummy1 === dummy3
和dummy2 === dummy4
不是运行时有效的表达(导致它们都崩溃).
因此,通过调用Unmanaged
API返回的指针似乎只应该与Unmanaged
API一起使用,以检索指针指向的值.withUnsafePointer
个API也是如此.为什么?
在@Sweeper的帮助下,我测试了示例代码的另一个版本:
class Dummy {
let uuid = UUID()
}
func test() {
var dummy = Dummy()
let unmangedOpaquePointer = Unmanaged.passUnretained(dummy).toOpaque()
withUnsafeMutablePointer(to: &dummy) {
let fromWithUnsafeAPIPointer = UnsafeMutableRawPointer($0)
print(unmangedOpaquePointer == fromWithUnsafeAPIPointer) // false
let dummy1 = Unmanaged<Dummy>.fromOpaque(unmangedOpaquePointer).takeUnretainedValue()
let dummy2 = fromWithUnsafeAPIPointer.assumingMemoryBound(to: Dummy.self).pointee
let dummy3 = Unmanaged<Dummy>.fromOpaque(fromWithUnsafeAPIPointer).takeUnretainedValue()
let dummy4 = unmangedOpaquePointer.assumingMemoryBound(to: Dummy.self).pointee
print(dummy1 === dummy2) // true
print(dummy1 === dummy3) // EXC_BAD_ACCESS
print(dummy2 === dummy4) // EXC_BAD_ACCESS
}
}
test()
这纠正了使用withUnsafePointer
个API的错误方式.但结果是一样的.