views:

225

answers:

2

Hi everyone, I'm developing an iPhone app and have a question about memory management. Let's say I have a class called Company with a NSNumber property(nonatomic,retain) called Id. I do this:

Company *company = [[Company alloc] initWithId:[NSNumber numberWithInt:1]];

Id should now have a retain count of 1? Then I do:

NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:company];
[company release];

What will the retain count on Id be now? Still 1? I should add that in the dealloc method in Company I do [self.Id release]. The problem is that when i do this in my app and later try to access [[array objectAtIndex:0] Id] it is out of scope. From my point of view the array retains company and therefore I should be able to access Id "through" the array. Is this correct?

Edit: Forgot to say that when I remove [self.Id release] from Company the app works, if it's there it crashes...

Thanks!

+1  A: 

As for your specific question: yes, that's correct. The array retains any object added to it, and the Company instance should retain the Id object. (Aside: the property should be named id, not Id to follow Cocoa conventions.) This is assuming that you are retaining the value in the initWithId: method (using self.Id or [Id retain]).

I can't see anything wrong with your code. I think the error must be due to something you do between adding the Company object to the array and trying to access it again. Are you saying that the error occurs after you add the [self.Id release]; line to dealloc? That would also be very strange.

It sounds to me like either you have over-released the Company object, or the array itself has been released. Could you try to produce a small code example which produces the bug (instead of just saying "later I do this and...")?

A more general answer is that you shouldn't think about what the exact retain count might be. The retain count will often be higher than what you expected because of the internal workings of Cocoa. What you should keep track of is merely which classes take ownership of an object (NSArray and NSMutableArray do, for example) and in which situations your own code should/shouldn't take ownership of an object. So when you ask if the retain count is still 1, that's slightly beside the point. The issue is whether any object still has ownership of the object in question.

Felixyz
Or, do `myIdMember = [myIdArgument retain]` in `initWithId:`.
Dirk
Thanks for a thorough answer!Yes, if I remove [self.Id release] from dealloc the app works as expected - feels very strange.The code I posted is a simplification of what I really do.However, as said, since everything works when I remove [self.Id release] can I draw the conclusion that I over-release Id and I simply don't need to do it in the Company class? Don't fix something that ain't broken right? =)
Michael Frost
I don't believe you can name variables/properties the same as "id" -- it's a type!
chpwn
Oh. My question was more of principles. In my app it's actually called companyId.
Michael Frost
@chpwn You can, in fact. I'm not saying it's good though. My point was just not to capitalize the ivar. More on using id etc as variable names: http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c
Felixyz
I didn't know that, I just assumed you couldn't, and used stuff like "identifier" instead as a replacement :p.
chpwn
@Michael Frost: No you should absolutely release id in the dealloc method. There must be something else wrong somewhere else. Try to create a more compact example that will cause the bug if you need more advice.
Felixyz
Well it's solved now. Did some rebuilds and I'm not sure exactly what was wrong. However, you answered my original question, thanks!
Michael Frost
+2  A: 

First, don't think of retain counts in terms of a specific number. Think of retains as a delta; you increment or decrement a retain count only.

To answer your specific question:

What will the retain count on Id be now? Still 1? I should add that in the dealloc method in Company I do [self.Id release]. The problem is that when i do this in my app and later try to access [[array objectAtIndex:0] Id] it is out of scope. From my point of view the array retains company and therefore I should be able to access Id "through" the array. Is this correct?

The retain count of Id is an implementation detail; NSNumber caches a small subset of values and, thus, the retain count may be some value entirely unrelated to anything you might expect if you consider retain counts in absolute terms.

If you try to access an object after you have balanced all retains with releases, then you are not following the memory management guidelines correctly.

Assuming that your "company" instance retains the instance of NSNumber then, yes, it should still be viable. What does "out of scope" mean? Do you have a runtime or compiler error? Post it, if you do.

bbum