开发者

Objects creation and instantiation in objective-c

开发者 https://www.devze.com 2023-03-18 20:59 出处:网络
Given the piece of code below where blueViewController is an iVar. Question: Why开发者_JAVA技巧 not instantiate the iVar directly?

Given the piece of code below where blueViewController is an iVar.

Question: Why开发者_JAVA技巧 not instantiate the iVar directly?

BlueViewController *blueController = [[BlueViewController alloc]initWithNibName:@"BlueView" bundle:nil];
self.blueViewController = blueController;
[blueController release];


It depends on where you are in your class. If you are in your init (and dealloc) method it is recommended to refer to the ivar directly to avoid any side effects in setter logic. Therefore in the init I would do

_blueViewController = [[BlueViewController alloc] initWithNibName:@"BlueView" bundle:nil];

But anywhere else I would do it how you have done it. Then if there is any custom logic in the getter/setter I know it will be run.

To eleborate on @Vladimar's point the synthesized setter for a retain will do some memory management similar to this:

- (void)setMyObject:(MyObject *)newMyObject
{
  // If it's the same object we don't need to do anything
  if (_myObject != newMyObject) {
    [newMyObject retain];
    [_myObject release];
    _myObject = newMyObject;
  }
}

It is much safer to let the getters/setters worry about all this logic any time you set your ivars.


You can initialise iVar directly, but the code you have also handles memory management for the previous blueViewController value. Accessing iVar directly you'll have to release previous value manually before assigning new one.


You can do it all on one line if you want. The important thing is to balance the +alloc with a -release or -autorelease. So, you can say:

self.blueViewController = [[[BlueViewController alloc] initWithNibName:@"BlueView" bundle:nil] autorelease];

That's fine, but some folks prefer to avoid -autorelease, and some folks just prefer simpler steps and/or shorter lines of code. Using an intermediate variable as you've done helps in that respect, and it doesn't cost anything.


It depends on whether the property is retain or not. Most object properties are retained; this is what a retain property looks like:

- (void)setBlueViewController:(BlueViewController *)bvc {
    if (bvc != blueViewController) {    // blueViewController is local ivar
        [blueViewController release];
        blueViewController = [bvc retain];
    }
}

So what you're doing up there is creating a retain count of +2. When you init, that's a +1; the property then retains it, bumping it up to +2. Your dealloc releases it once, which brings it down to +1...and you've leaked that property. Because you are alloc/init-ing the variable, you don't want to use the setter; instead, assign it directly to the instance variable.

By instantiating it directly, it saves you the trouble of that other release—fewer lines of code means fewer errors. You might, for example, have typed retain by accident and not realized it until your program crashes because you retained a massive class...

Of course, as Caleb says you could autorelease, but that's effectively letting the object lie around in memory until the run loop is finished. It's much easier, and gives you more control, to just not worry about that. There's nothing wrong with assigning the alloc/init to the ivar; in fact, that's the best way to do it.

0

精彩评论

暂无评论...
验证码 换一张
取 消