Below is the sample code I use:
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()
- different UnsafeMutableRawPointer instances
print(unmangedOpaquePointer == fromWithUnsafeAPIPointer) // false
The result of the above code snippet is “false”. It’s kind of expected. unmangedOpaquePointer and fromWithUnsafeAPIPointer are different instances of UnsafeMutableRawPointer
, so they are not equal.
However, they both point to the same object dummy here. How can I test this piece of fact, if unmangedOpaquePointer == fromWithUnsafeAPIPointer
is not the right way to achieve it?
- API calls should be paired? Why? What’s the difference between the UnsafeMutableRawPointer returned from
Unmanaged
APIs and thewithUnsafePointer
APIs?
print(dummy1 === dummy2) // true
The print
call says dummy1 and dummy2 retrieved from the two pointers are identical (the same object instance). However dummy1 === dummy3
and dummy2 === dummy4
are not runtime valid expressions (cause they both crash).
So it seems the pointer returned by calling an Unmanaged
API should only be used with an Unmanaged
API to retrieve the value that the pointer points to. The same goes for withUnsafePointer
APIs. Why?