views:

48

answers:

2

I have a simple question. I was referring "Your first iOS application" document by apple.I found that the class has a property called myViewController:

@interface applicationClass
{
   MyViewController *myViewController
}

Now to assign a memory to this pointer, the code shown is:

MyViewController *aViewController = [[MyViewController alloc]
            initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]];
[self setMyViewController:aViewController];
[aViewController release];

My doubt here is, what is wrong if this is done as follows:

self.myViewController = [[MyViewController alloc]
            initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]];

I cannot find this kind of instantiation where a property is assigned directly in many of the documents. Instead, a temporary memory is allocated and then it is retained by the property. Can anyone guide me if I am wrong ?

A: 

With this you are retaining your object twice: in self. (if you have set retain in your property of couse) and in [MyViewController alloc]. You only want to retain the object once ....

toupper
If I do this, I am retaining the object in self (assuming I set retain in property). But how does [[MyViewController] alloc] cause another retain ? When I say [anObject alloc], memory is allocated for that object and given to any pointer responsible for the same right ? Could you please elaborate the second point ?
tuttu47
A: 

If you call methods which have alloc or copy in their names you get objects with a retain count of +1 and thus you are responsible for releasing it after use.

Now, if you assign to a property that is defined as @property(retain,...) ... then the @synthesize'd method takes care that retain and release are called correctly. So if you do self.foo = bar then the retain count of bar is increased by one.

Here, you got an object with retain count 1 from your alloc/init. Then you assign it to your property, and the retain count climbs to 2, which is too high (you only have one reference to it, not two). Two solutions: either the first code block you've cited, it stores the object in a variable and can then call release to immediately "fix" the retain count to 1 again. Or, you can do this:

self.myViewController = [[[MyViewController alloc] initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]] autorelease];

The autorelease will make sure that at a later time release is being called on the object thus again "fixing" the retain count. You cannot replace autorelease withrelease` here as the retain count would drop to 0 before it gets assigned to the property, thus it would get deallocated before it gets passed to the property.

DarkDust
Thank you very much for the quick and elaborate answer. I understand it well. However a small doubt. In the case that I said above, since the sole owner of the memory is self.myViewController and this has a retain count of 2, can I release it twice to fix the same problem ? I know this is kind of creepy question, but just wanted to know if this is technically feasible !
tuttu47
Yes, you can do `self.foo = [[Bar alloc] init]; [self.foo release];` to get a retain count of 1 (if you would release it twice the count would be 0 and the object would be released which is not what you want because the variable/property would still point to that memory location and think it's alive, causing trouble and crashes). I've never seen this so far as most Obj-C developers instinctively seem to use `autorelease` here or do the manual approach in your first code example, but I don't see anything wrong with this solution.
DarkDust