In rare cases (which are growing rarer by the day) a Core Foundation function may return a C-pointer or an object reference embedded into an Unmanaged wrapper. You encounter these in the older, dustier, and stranger parts of Cocoa where grues still lurk in shadows. You must transfer Unmanaged references into the normal memory management system before working with them in Swift .
Here’s my current understanding of the situation. Feel free to correct any mistakes and I’ll update this post.
An Unmanaged wrapper, like an Optional wrapper, provides a layer of safety between your code and a potentially nasty crash. The Unmanaged<T> type stores a pointer whose memory is not controlled by the Swift runtime system. Before using this data, you take responsibility for how this memory should stay alive.
In Cocoa, this works very much like bridging in Objective-C. Unwrap any object with an existing +1 retain count using takeRetainedValue(). This applies to any item built with Create or Copy in its name.
For example, UTTypeCopyPreferredTagWithClass returns a +1 CFString instance. Assign this result with takeRetainedValue(), making sure to test for failed calls. Unwrapping nil causes nasty crashes that even blessed potions of restore life will not fix. (In Swift, there is no @try, there is only d’oh!) (And potentially d’oh not, if you listen to that Yoda guy.)
public func PreferredFileExtensionForUTI(uti: String) -> String? {
if let result = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension) {
return result.takeRetainedValue() as String
} else {
return nil
}
}
Use takeUnretainedValue() to unwrap any object built by a Core Foundation function with Get in its name (for example, CFAllocatorGetDefault()) and constants passed as unmanaged objects (for example kLSSharedFileListSessionLoginItems). These items are not automatically retained for you. Unlike takeRetainedValue(), calling takeUnretainedValue() will not consume a retain upon unwrapping.
These functions follow the patterns established in Apple’s Memory Management Programming Guide for Core Foundation, where you can read more about the “Create Rule”, the “Get Rule”, and other details about memory ownership policies.
Update: Cocoa Kevin writes “If you have an Objective-C framework or are developing one that you would like people to use in their Swift application and there are methods or functions in your Objective-C framework that return CoreFoundation objects, you need to decorate your methods or function names with CF_RETURNS_RETAINED or CF_RETURNS_NOT_RETAINED. The CoreFoundation naming rules is not enough according to the Swift compiler. If you don’t decorate your methods or functions then CoreFoundation objects will be returned as unmanaged.”
Comments are closed.