views:

64

answers:

3

I'm running into a retain count issue that I do not understand. (I've added what I believe to be the retain count of vertex in [] at the end of each line of code).

CBVertex *vertex = nil;
for(int i=0; i<10; i++) {
    vertex = [[CBVertex alloc] initWithFrame:CGRectMake(minX, y, 10.0, 10.0)]; // retain count [1]
    [vertex setTag:i];
    [vertex setAnimationDelegate:self];
    [gameboard addSubview:vertex];   // retain count [2]
    [tripGraph addVertex:vertex];    // retain count [3]
    [vertex release]; vertex=nil;    // retain count [2]
}

CBVertex is a subclass of UIView, gameboard is a UIView and tripGraph is a class that, among other things, has an NSMutableArray (privateVerticies) to which vertex is added to in its addVertex method.

After the above is executed, Instruments shows that there are 10 instances of CBVertex living.

Later in the code execution (I've confirmed that this code executes):

[[tripGraph verticies] makeObjectsPerformSelector:@selector(removeFromSuperview)];
// gameboard should have no references to any of the CBVertex's (correct??)

[tripGraph removeAllVerticies]; 
// tripGraph privateVerticies is empty and  no references to any of 
// the CBVertex's (correct?)

Relevant tripGraph methods:

-(NSArray *) verticies {
   return [NSArray arrayWithArray:privateVerticies];
}

-(void) tripGraph removeAllVerticies {
   [privateVerticies removeAllObjects];
}

- (void) addVertex:(CBVertex *)vertex {
   [privateVerticies addObject:vertex];
}

The issue arises when the second set of CBVertex's are created. Instruments shows that the first set of CBVertex's is still live (i.e. the number of instances of CBVertexs is now 20).

I'm (obviously?) missing a release somewhere, but don't understand where . . .

Help/pointers are appreciated!!

thanks

tom

A: 

If gameboard and tripGraph are still retaining that CBVertex object, then even if you release it in your loop, it will continue to exist until you remove the CBVertex object from gameboard and tripGraph as well.

macatomy
yup -- and they are removed from tripGraph and gameboard in the code shown. (Which I've confirmed is executed)
TomH
A: 

OK, I'm closing this out as the code above is correct. The problem lies in my overriden removeFromSuperview method in which there is an animation going on. I'm going to investigate further and if I don't have it figured out, I'll repost a new question. (and link to it from here).

Thanks for the comments, answer and several views.

TomH
A: 

For those interested, here's what was going on and how it was resolved.

In CBVertex, I've overridden removeFromSuperview. In that overridden method, I am animating the view's layer and setting the view as the CAAnimations delegate (which is retained by the CAAnimation) and calling super removeFromSuperview. The animation is not removed on completion.

As the animation retains the delegate and the animation is not removed, the view's retain count remains at +1.

My resolution was to create an intermediate method to perform the animation. When the animation is complete it calls the overriden removeFromSuperview, which now only removes all animations and calls super. Removing the animation releases it, which in turn releases it's reference to it's delegate (the CBVertex) and the CBVertex's retain count goes to +0.

One final thought for anyone chasing retain counts: don't think of them as absolute values. The inner workings of the objects you may be using might be retaining your instances more than you'd expect -- think of retain counts as a delta.

SomeClass *myObject = [[SomeClass alloc] init]; // retain count +1
[someMutableSet addObject:myObject]; // retain count +2
TomH