When to Use Takeunretainedvalue() or Takeretainedvalue() to Retrieve Unmanaged Objects in Swift

When to use takeUnretainedValue() or takeRetainedValue() to retrieve Unmanaged Objects in Swift?

You use takeRetainedValue when the unmanaged object has a +1 retain count and you want ARC to take care of releasing the object when you're done. For example, if you call a Core Foundation function with Create or Copy in the name (see Create Rule in the Memory Management Programming Guide for Core Foundation) which returns an unmanaged object for which you are responsible for releasing, you generally use takeRetainedValue so that it is released for you (or, if you don't do this, you have to manually release it yourself with CFRelease or similar function). You use takeUnretainedValue when ownership of the object has not been transferred to you and you therefore do not want ARC releasing the object for you when it falls out of scope.

So, as to when you call takeUnretainedValue vs takeRetainedValue, it simply depends upon what sort of object the called function returns. As a general rule of thumb, if the object was returned from a Core Foundation function with Create or Copy in the name, use takeRetainedValue. Otherwise use takeUnretainedValue.


In terms of what happens if you call the wrong method, if you call takeUnretainedValue when you're passed a +1 object (e.g. an object returned from Core Foundation function with Create or Copy in the name), your app will leak unless you explicitly CFRelease it. You may not immediately notice the occasional leak when running the app, but it can be observed by watching your app's memory usage (e.g. if you profile your app with Instruments). But if you leave these leaks unresolved, your app may eventually receive memory warnings.

On the other hand, if you call takeRetainedValue on an object which has not been retained for you (returned by a function that did not have Create or Copy in its name), the app will likely crash when the object is released. Sometimes this won't manifest itself immediately (not until the last strong reference is resolved), but it will generally result in a catastrophic failure of the app.

So judicious selection of takeUnretainedValue vs takeRetainedValue is very important.

What's the difference between takeUnretainedValue and takeRetainedValue?


how do I know whether the unmanaged object is an unretained or retained object?

It depends on which API you use.

There are some Conventions here: Ownership Polocy / Memory Management Programming Guide for Core Foundation

Basically, if a function name contains the word "Create" or "Copy", use .takeRetainedValue(). If a function name contains the word "Get", use .takeUnretainedValue().

And, if it does not contains either, as far as I know, we can still use .takeUnretainedValue() in almost every cases.

However, every rule has an exception :) for example, see:

Swift UnsafeMutablePointer<Unmanaged<CFString>?> allocation and print

takeRetainedValue() or takeUnretainedValue() in Swift with C++ Library

You need to pass in a retained value if you want your ClassCallback to exist even if all your Swift references to it go away, this creates a memory leak without proper cleanup logic also being added in. If you pass an unretained value then if all of your swift references have gone away when you try to get back your ClassCallback you will crash.

In your callback, you can take an unretained reference to get the object assuming you want it to continue to exist with its current reference count at the end of scope. If you take a retained reference the reference count will decrement and destroy the object if that was the last reference.

What I generally do is pass in a retained reference and take an unretained reference until I am ready to dispose of the callback object. When that happens I take the retained value of the context pointer (aPtr in your case) to balance the retained pass and replace it with a new appropriate value.

Swift C callback - takeUnretainedValue or takeRetainedValue for Swift class pointer

An object pointer can be converted to a Unsafe(Mutable)RawPointer (the Swift
equivalent of the C void *) with or without retaining the object:

let ptr = UnsafeMutableRawPointer(Unmanaged.passUnretained(obj).toOpaque())
// Does not retain `obj`

let ptr = UnsafeMutableRawPointer(Unmanaged.passRetained(obj).toOpaque())
// Retains `obj`

The conversion back to an object pointer (often done in a callback
function called from C) can be with or without consuming a retain:

let obj = Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
// Does not consume a retain

let obj = Unmanaged<T>.fromOpaque(ptr).takeRetainedValue()
// Consumes a retain

If the lifetime of obj is guaranteed while the callback is active
then the easiest way is to use the "unretained" conversions in both directions. You are responsible for retaining obj while the
callback is active, e.g. by unregistering the callback before obj
is deinitialized.

The alternative is to use passRetained() to convert obj to
a pointer. This retains the object and therefore keeps it "alive".
The callback can still use the "unretained" conversion to convert
the pointer to an object pointer, without decreasing the retain count.
But there must be exactly one takeRetainedValue() call to consume the
retain. After that, the object can be destroyed if there are no
other references to it.

More generally, each call to passRetained(obj) increases the retain
count and each call to takeRetainedValue() decreases it, so they must be properly balanced.

How do I return an Unmanaged CGColor ! in Swift

You can create Unmanaged instance by calling passRetained or passUnretained static function like this:

Unmanaged.passRetained(UIColor.white.cgColor)

But keep in mind, that for future usage of this variable should be handled with takeRetainedValue if you decided to use passRetained() or with takeUnretainedValue() function if you will use passUnretained. If that would not be done - you would have memory leak or possible crash.

Get value as swift type from Unmanaged AnyObject . For example: ABRecordRef

Since NoOne answered before I solved it, I'll add the answer here:

firstName.takeRetainedValue() as? String

If you look at the header of the Unmanaged struct type, you'll find this:

/// Get the value of this unmanaged reference as a managed
/// reference and consume an unbalanced retain of it.
///
/// This is useful when a function returns an unmanaged reference
/// and you know that you're responsible for releasing the result.
func takeRetainedValue() -> T

So, because the CFTypeRef is converted to Unmanaged<AnyObject> in Swift.

Unmanaged uses generics to define a return type, and it is declared like so:

Unmanaged<T> 

Our object is of type Unmanaged<AnyObject> which means that takeRetainedValue() will return type T, or in our case, type AnyObject. I use optional downcasting since my property firstName is of type String?.

You can use the takeRetainedValue method to get your value out of your Unmanaged object. In Foundation API's, I'm guessing that they will mostly be of type Unmanaged<AnyObject>! and a downcast will be required. The generic formula appears to be:

var unmanagedObject: Unmanaged<AnyObject> = someFunctionThatReturnsAnUnmanagedObject()
var newValue: Type = unmanagedObject.takeRetainedValue as Type

How to convert Unmanaged CFTypeRef to Swift 3


AddressBook framework is deprecated as of iOS9, and at any time Apple
would say: "AddressBook is actually removed from iOS 10.x". You better
get ready for Contacts framework soon.

You are using so redundant code that some parts are not needed even in Swift2.

To retrieve T object from Unmanaged<T>?, you just need to call takeRetainedValue() or takeUnretainedValue() immediately.

let phones: ABMultiValue? = unmanagedPhones?.takeRetainedValue()
  • You should use takeRetainedValue() for the result of Copy-ruled functions.
  • ABMultiValue is a typealias of CFTypeRef in Swift3, so you have no need to cast the result.
  • Care about nil-safe coding, as Unmanaged<T>? may be nil.

Get a CGImageRef from an IKImageView in Swift

This has to do with the bridging of Objective C APIs into Swift. The Swift versions of an API have been bridged (mostly automatically, I believe) by converting the original Objective C headers into a Swift version. In many cases, the conversion can work out what kind of value you're going to get back, and therefore in Swift you get a "normal" type that you can use as you'd expect.

However, the conversion is still a work in progress. In this case, what you're seeing is a type used to help you manage memory manually when the conversion process doesn't know whether you're going to get back an object that's been retained for you or not, because the API doesn't have the conventional annotation that it could use to figure it out.

The Unmanaged type effectively says "you have to tell me what to do with the contained value to get the memory management right". As soon as you get an Unmanaged value, you should call either one of its two methods:

takeUnretainedValue() 
takeRetainedValue()

...depending on whether the object you get back was a "+0" or "+1". So, you're expected to do something like:

var newImage: CGImage = imageView.image().takeUnretainedValue()

And as soon as you've done that (which you should do pretty much immediately), you've given Swift enough of a hint that it can now appropriately manage the object correctly with ARC, and got yourself a valid reference of the right type.

This is touched on briefly at the end of the "Swift Interoperability in Depth" WWDC video from this year.



Related Topics



Leave a reply



Submit