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 ofCopy
-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
Avcapturesession and Background Audio iOS 7
Linker Error in iOS (Duplicate Symbols for Architecture X86_64)
How Does Xcode Find Implicit Target Dependencies
Decimal to Fraction Conversion in Swift
Could Not Load the "" Image Referenced from a Nib in the Bundle with Identifier
Swiftui: What Is @Appstorage Property Wrapper
Keyboard and Cursor Show, But I Can't Type Inside Uitextfields and Uitextviews
How to Get a Cgpoint from a Tapped Location
Using Ldap for Authentication in iOS
Swift 3 - Comparing Date Objects
Uicollectionview - Diddeselectitematindexpath Not Called If Cell Is Selected
How to Get Only Images in the Camera Roll Using Photos Framework