views:

110

answers:

4

I'm new to the memory management of the iphone and had a question about standards/correctness.

My header file declares:

 IBOutlet UITabBarController *tabBarController;
 @property (nonatomic, retain) UITabBarController *tabBarController;

In my init() code I was doing something like the following:

self.tabBarController = [[UITabBarController alloc] init];
[tabBarController release];
NSLog(@"Retain count of tbc: %d",[tabBarController retainCount]);

to get the retain count back to one. Is this correct from a standardization point of view? It just looked a bit different to me, but again I'm new to this.

Thanks

+1  A: 

Why not

tabBarController = [[UITabBarController alloc] init];

?

mustISignUp
This made sense to me as well - to do it this way and leave out the synthesized setter method. In this case I checked the retain count - which was now at 2 - and found myself releasing the thing myself, which was odd to me. I appreciate the tip - I'm going this route now.
inyourcorner
+1  A: 

You could do it this way, but better is to not use this implicit setter syntax in your init() method (because you might override the setter and do further stuff that might not work yet if the object is not fully initialized).

Just do:

tabBarController = [[UITabBarController alloc] init];
Felix Kling
This can leak the previous value if you put it in the wrong place and it gets called more than once. In a view controller for example, it's OK in awakeFromNib, but not viewDidLoad.
progrmr
@progrmr: I am referring to the `init()` method and I guess `tabBarController` will not have had another value before `init()` gets called.
Felix Kling
+2  A: 

For assigning to the property, you should either use

self.tabBarController = [[[UITabBarController alloc] init] autorelease];

or

[tabBarController release];
tabBarController = [[UITabBarController alloc] init];

(Remember to release the previous value first)

The property setters/getters should be solely responsible for retaining/releasing the instance variable. What happens if you (or somebody else) changes the property setter to take a copy of the input instead of retaining it? In that case you are going to over-release the instance variable and leak the original object.

You are essentially sending a message which has private side-effects, and then using knowledge of those private details by releasing the instance variable on the next line. i.e. your code is the same as:

[self setTabBarControler:[[UITabBarController alloc] init]];
/* Relying on knowledge of the instance variable is bad here, setTabBarController
   might do something different in the future */
[tabBarController release];

Even though you are in full control of the class, you should still adhere to the basic principles of abstraction and encapsulation. Leave the retaining/releasing of instance variables to the underlying property implementation.

Mike Weller
releasing an instance variable on the first line of an init method is crazy talk.
mustISignUp
I'm learning from a book, and the book pushes @property()'s; should I really even use that notation in this case? Or handle the alloc init myself?
inyourcorner
@property()'s are syntactic sugar for accessor methods. So the question is should you use the setter accessor method (that's what using the property would do for you) or not (either way you have to handle the alloc/init) ? Normally you should use the setter method to enable observers of your property to be notified of updates, but that isn't relevant in an init method. Also, if the setter method is overridden in a subclass this would cause it to be called before the subclass is initialised - and that would be bad.
mustISignUp
+3  A: 

That's normal.

What you do:

self.tabBarController = [[UITabBarController alloc] init];
[tabBarController release];

maybe performed by compiler as:

id *tempVar = [[UITabBarController alloc] init];
self.tabBarController = tempVar;                  //till now, retainCount is 2
[tabBarController release];                       //now, retainCount is 1

When you alloc it, this memory block will be retained by a temporary var. So a better way to do that is:

UITabBarController *tabCtl = [[UITabBarController alloc] init];
self.tabBarController = tabCtl;
[tabCtl release];

I'm not an expert of object-c, just have some knowledge about compiling. So, if I'm wrong, experts here please point out.

Elliot Chen