When interfacing with C APIs, one might want to back off Swift reference counter. Doing so is achieved with unmanaged objects.
If you need to supply a type-punned pointer to a C function, use toOpaque
method of the Unmanaged
structure to obtain a raw pointer, and fromOpaque
to recover the original instance:
setupDisplayLink() {
let pointerToSelf: UnsafeRawPointer = Unmanaged.passUnretained(self).toOpaque()
CVDisplayLinkSetOutputCallback(self.displayLink, self.redraw, pointerToSelf)
}
func redraw(pointerToSelf: UnsafeRawPointer, /* args omitted */) {
let recoveredSelf = Unmanaged<Self>.fromOpaque(pointerToSelf).takeUnretainedValue()
recoveredSelf.doRedraw()
}
Note that, if using passUnretained
and counterparts, it's necessary to take all precautions as with unowned
references.
To interact with legacy Objective-C APIs, one might want to manually affect reference count of a certain object. For that Unmanaged
has respective methods retain
and release
. Nonetheless, it is more desired to use passRetained
and takeRetainedValue
, which perform retaining before returning the result:
func preferredFilenameExtension(for uti: String) -> String! {
let result = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension)
guard result != nil else { return nil }
return result!.takeRetainedValue() as String
}
These solutions should always be the last resort, and language-native APIs sould always be preferred.