18

Note: This other question seems relevant but it's not: When does an associated object get released?

I'm adding a second description to a UIView instance as follows:

- (void) setSecondDescription:(UIView*)view description2:(NSString*)description2 {
    objc_setAssociatedObject (view,&key,description2,OBJC_ASSOCIATION_RETAIN);
}

- (NSString*) secondDescription:(UIView*)view {
    return (id)objc_getAssociatedObject(view, &key);   
}

If the UIView deallocs, will the associated description 2 get dealloced? Is there any way to get this to happen automatically?

Community
  • 1
  • 1
Dan Rosenstark
  • 68,471
  • 58
  • 283
  • 421

4 Answers4

72

If you want to actually see the description of the entire dealloc timeline, look at WWDC 2011, Session 322, 36:22. However, here's the basic rundown (I wanted to remember it, so this is an actual comment in a piece of my code).

Note, that the associated objects are released at the end of the life cycle.

// General Information
// We take advantage of the documented Deallocation Timeline (WWDC 2011, Session 322, 36:22).
// 1. -release to zero
//     * Object is now deallocating and will die.
//     * New __weak references are not allowed, and will get nil.
//     * [self dealloc] is called
// 2. Subclass -dealloc
//     * bottom-most subclass -dealloc is called
//     * Non-ARC code manually releases iVars
//     * Walk the super-class chain calling -dealloc
// 3. NSObject -dealloc
//     * Simply calls the ObjC runtime object_dispose()
// 4. object_dispose()
//     * Call destructors for C++ iVars
//     * Call -release for ARC iVars
//     * Erase associated references
//     * Erase __weak references
//     * Call free()
Jody Hagins
  • 27,943
  • 6
  • 58
  • 87
  • +1 This is great stuff, Jody. I might have to actually watch the session, since I cannot understand *where* this code would be located. But that's more my lack of understanding of how Obj-C is put together than anything. – Dan Rosenstark Jun 01 '12 at 02:12
  • 1
    When the reference count goes to 0, the object begins to die, and this code path is executed. There is some setup to disallow new weak references, and some other stuff, and then the dealloc chain begins. When the dealloc chain is done, that's when all the instance variables are destroyed (under ARC). The associated objects are just a map that is attached along with the rest of the stuff (well, it used to be a std::map<> - I have not looked lately, but I have really wanted them to use an array for small numbers of associated objects, then use a map later - to limit memory consumption). – Jody Hagins Jun 01 '12 at 02:27
  • This is a great piece of information Jody, thanks. Just like to add that I found out that in iOS4, if you add associated objects to an object that is also registered as an observer, the associated objects will never be released even though the object does get released. So using KVO in combination with associated objects in iOS4 breaks this chain somehow. – David Oct 31 '12 at 09:47
3

Yes. When an object is dealloc'd, any associated objects (that use the RETAIN or COPY association types) are automatically released.

Lily Ballard
  • 182,031
  • 33
  • 381
  • 347
3

In short, yes - when the owning object is released then retained associated objects are released. See the first section of Apple's documentation

CRD
  • 52,522
  • 5
  • 70
  • 86
  • I have seen that section. Where does it say that it's released? – Dan Rosenstark Jun 01 '12 at 00:32
  • @Yar quite clearly in the 2nd to last sentence of the first section (Creating Associations): "When the array is deallocated, however (at point 2), overview is released and so in this case also deallocated." :) – borrrden Jun 01 '12 at 01:58
2

Section 4 in Jody Hagins' answer says "Erase associated references", which doesn't explicitly imply that the references are released. So I used the following piece of code (note WITHOUT ARC) to test this.

@interface AssociatedObjectHelper : NSObject
@end

@implementation AssociatedObjectHelper
- (void) dealloc
{
    NSLog(@"In %s", __FUNCTION__);
    [super dealloc];
}
@end

@implementation AppDelegate
...
- (void) testReleaseAssociatedObject
{
    static const NSString *key = @"testKey123";
    NSObject *ob = [NSObject new];
    AssociatedObjectHelper *assocOb = [AssociatedObjectHelper new];
    objc_setAssociatedObject(ob, key, assocOb, OBJC_ASSOCIATION_RETAIN);
    [assocOb release];
    [ob release];
}

Invoking above code does indeed end up calling -[AssociatedObjectHelper dealloc], with the following stack-trace:

#0  0x000000010000528f in -[AssociatedObjectHelper dealloc]
#1  0x00007fff8a0bb89c in objc_object::sidetable_release(bool) ()
#2  0x00007fff8a0a537f in _object_remove_assocations ()
#3  0x00007fff8a0a1644 in objc_destructInstance ()
#4  0x00007fff8a0a1595 in object_dispose ()
#5  0x00007fff8a0bb89c in objc_object::sidetable_release(bool) ()
#6  0x000000010000e9b6 in -[AppDelegate testReleaseAssociatedObject]

Tested on Xcode 7.0.1

Community
  • 1
  • 1
Vivek
  • 564
  • 4
  • 13