Welcome to Core Foundation world! In Swift, the memory management for Core Foundation (as well as a series of other Core frameworks) is greatly simplified. It allows us to work better and easier with those Core Foundation (CF for short later) APIs.

First take a look at toll-free bridging in Cocoa. A lot of NS classes have their corresponding CF types. In fact, the NS prefixed classes are only a higher level encapsulation for the CF types. For example, NSURL has a similar memory structure with CFURLRef, and NSString is an abstract for CFStringRef, etc.

In Objective-C, ARC will only take the responsibility of reference counting for NSObject and its subclass. The memory of CF objects is not managed by ARC mechanism. When we convert objects from NS to CF or vice versa, we need to tell the compiler how does the memory ownership changes. For those situation that the memory owner does not change, we should add __bridge to describe it. The code below transforms an NSURL object to CFURLRef without transferring the memory ownership:

NSURL *fileURL = [NSURL URLWithString:@"SomeURL"];
SystemSoundID theSoundID;
OSStatus error =
        (__bridge CFURLRef)fileURL,

The fileURL object will be released properly when out of scope.

In Swift, thing gets simpler. We could rewrite the code above like this, which is much easier and cleaner:

let fileURL = NSURL(string: "SomeURL")
var theSoundID: SystemSoundID = 0
AudioServicesCreateSystemSoundID(fileURL, &theSoundID)

You may already find the CF type of URL is CFURL here, while in Objective-C it is CFURLRef. In Swift, CFURL is just a typealias of CFURL. Besides of URL, other CF types also follow this. The main purpose is reducing the confusing of the API name. In Swift, these CF types behave more like types under management of ARC. It will be clearer to remove the Ref from the type name.

In Objective-C, ARC cannot handle the creation and releasing of CF types. There is a naming convention in CF: If Create, Copy or Retain exists in a CF API, after using the instance, we need to use CFRelease to release the object.

But in Swift, this rule is not needed anymore. Developers asked, since we already have the name convention, why not just do the release for me? Yes! In Swift we never need to call the CFRelease method (actually you will get an error if you write it). In other words, CF types now are under control of ARC. The under hood is similar to invoking of release for NSObject, the compiler will insert CF_RETURNS_RETAINED or CF_RETURNS_NOT_RETAINED in proper position for us based on the code.

However, there is an exception. Swift cannot handle your own CF API. That means if you write your own method or use some third party code which returns an instance of CF type, you have to manage the memory yourself. There is no mechanism to force those codes to follow the Cocoa name convention, so it is not possible to auto management. If you didn't use the memory annotation in the methods, you will get a Unmanaged<T> instead of the CF type.

To manage the memory manually, we would use the takeUnretainedValue or takeRetainedValue method of the Unmanaged object to get out the corresponding CF object, and deal with its reference count at the same time. takeUnretainedValue will keep the reference count unchanged. When you know it is not your responsibility to release the object, you should use this to retrieve the CF object. Otherwise, if you hold that object, and must release it later, you should use takeRetainedValue to increase the reference count. After used, you should also release the original Unmanaged object manually. There are still retainrelease and autorelease methods for us to use. Generally speaking, when you use it, you might write like this:

// CFGetSomething() -> Unmanaged<Something>
// CFCreateSomething() -> Unmanaged<Something>
// There is no annotation. And a new instance is created in the "Create" API.

let unmanaged = CFGetSomething()
let something = unmanaged.takeUnretainedValue()
// After we called takeUnretainedValue, something is an instance of Something

let unmanaged = CFCreateSomething()
let something = unmanaged.takeRetainedValue()

// Use something

//  Since the value of unmanaged is retained, we should release it now

Remember, you might rarely use this, unless you are working with a lot of customized CF API. If your daily work is app development, it seems OK even you have no idea about memory management customized CF APIs.