Strange ARC issue not releasing ivar in UIView subclass

Possible Duplicate:
Why is object not dealloc'ed when using ARC + NSZombieEnabled

I’ve got a very strange issue I’m seeing at the moment in a project. Put simply I have ViewA which owns ViewB (strong property). ViewA creates its ViewB in its initialiser. Both objects are subclasses of UIView.

  • Retrieving data programmatically from a Configuration Profile in IOS
  • In Apple Swift, in what case(s) would I not want an implicitly unwrapped optional?
  • Correct way to create button in Sprite Kit?
  • Parse Sort Query Via Pointer
  • playing a WAV file on iOS Safari
  • Warning while adding and using a new method in external library protocol
  • I have overridden dealloc in both and put a log line and a break point to see if they get hit. It seems that ViewA‘s dealloc is being hit but not ViewB‘s. However if I put in a self.viewB = nil in the dealloc of ViewA then it is hit.

    So basically it’s something like this:

    @interface ViewA : UIView
    @property (nonatomic, strong) ViewB *viewB;
    @end
    
    @implementation ViewA
    
    - (id)initWithFrame:(CGRect)frame {
        if (self = [super initWithFrame:frame]) {
            self.viewB = [[ViewB alloc] initWithFrame:self.bounds];
            [self addSubview:self.viewB];
        }
        return self;
    }
    
    - (void)dealloc {
        //self.viewB = nil; ///< Toggling this commented/uncommented changes if ViewB's dealloc gets called.
        NSLog(@"ViewA dealloc");
    }
    
    @end
    

    What I can’t understand is why nil-ing viewB out makes a difference. If something else is holding onto viewB then it should make absolutely no difference if I nil it out or not here. And it shouldn’t make a difference to the number of releases that ARC adds in either.

    I can’t seem to reproduce it in a minimal test case as yet, but I’m working on it. And I can’t post the actual code I’m seeing this in unfortunately. I don’t see that being an issue though because it’s more the point that nil-ing it out shouldn’t make a difference that I am confused by.

    Can anyone see anything I am overlooking or give advice about where to look for debugging this problem?

    Update:

    I’ve found the problem. It appears that it’s only a problem when NSZombieEnabled is set to YES. Well that is entirely mad and has to be a bug surely. Zombies should not affect how this works as far as I know. The objects should still go through the dealloc method. And what’s more, it’s just mad that it works if I nil out viewB in ViewA‘s dealloc.

    Solutions Collect From Internet About “Strange ARC issue not releasing ivar in UIView subclass”

    I’ve found that this appears to be a bug in the iOS implementation of zombies. Consider the following code:

    #import <Foundation/Foundation.h>
    
    @interface ClassB : NSObject
    @end
    
    @implementation ClassB
    - (id)init {
        if ((self = [super init])) {
        }
        return self;
    }
    - (void)dealloc {
        NSLog(@"ClassB dealloc");
    }
    @end
    
    @interface ClassA : NSObject
    @property (nonatomic, strong) ClassB *b;
    @end
    
    @implementation ClassA
    @synthesize b;
    - (id)init {
        if ((self = [super init])) {
            b = [[ClassB alloc] init];
        }
        return self;
    }
    - (void)dealloc {
        NSLog(@"ClassA dealloc");
    }
    @end
    
    int main() {
        ClassA *a = [[ClassA alloc] init];
        return 0;
    }
    

    That should output:

    ClassA dealloc
    ClassB dealloc
    

    But with NSZombieEnabled set to YES, it outputs:

    ClassA dealloc
    

    As far as I can tell, this is a bug. It seems to only happen with iOS (both simulator and device) and does not happen when built and run for Mac OS X. I’ve filed a radar with Apple.

    Edit: It turns out this has already been answered here – Why is object not dealloc'ed when using ARC + NSZombieEnabled . Managed to find it after I found out what the real problem was. It’s nothing to do with ARC by the way.