Weak object in an NSDictionary?

I would like to store a zeroing weak reference to an object in a NSDictionary. This is for a reference to a parent NSDictionary, so I can crawl back up a large structure without searching.

I can not use __weak here; even if my local reference is weak, the NSDictionary will store a strong reference to the object that was weakly referenced. And, of course, NSDictionary can’t have nil objects.

  • Is there way to check a `unowned` (actually `unowned(safe)`) reference has been deinited?
  • Two weak variables referencing each other in Swift?
  • Iterate array of weak references where objects conform to a protocol in Swift
  • Where does the weak self go?
  • Why can the keyword “weak” only be applied to class and class-bound protocol types
  • Creating views programmatically Strong Vs Weak subviews in controller
  • I’m on iOS, not Mac, so NSHashTable isn’t available. And I only want one object to be weak; the rest should still be strong.

    (I’m going to post my answer, so I have something to mark as accepted if there’s no better answer. But I’m hoping someone has a better answer.)

    3 Solutions Collect From Internet About “Weak object in an NSDictionary?”

    In iOS 6+ you can use NSMapTable and choose if you want objects and/or keys to be weak or strong.

    I’ve settled on defining a “container” class with a single member, like this:

    @interface Parent : NSObject
    @property (nonatomic, weak) id parent;
    @end
    
    @implementation Parent
    
    @synthesize parent = _parent;
    
    - (id)initWithParent: (id)parent;
    {
        if (( self = [super init] )) {
            _parent = parent;
        }
        return self;
    }
    @end
    

    And using it:

    id parentRef = [[Parent alloc] initWithParent: parent];
    [newElement setObject: parentRef forKey: ParentKey];
    

    I think this will work for me, but it seems crazy that there’s no better way built in to Foundation.

    There is a built-in way; just use:

    [array addObject:[NSValue valueWithNonretainedObject:object]];
    

    Then to access the object later, use:

    id object = [[array objectAtIndex:i] nonretainedObjectValue];
    

    If the value has been released since you added it then “object” will be an invalid pointer under iOS 4.x, and (I’m assuming) will be nil under 5.x with ARC enabled.

    EDIT: my assumption was wrong – it’s not weak under ARC (see discussion below).