views:

83

answers:

4

When you synthesize a property (see below)

@interface CelestialBody : NSObject {
    NSString *name;
}
...

@interface Planet : NSObject {
    NSString *name;
    int mass;
    CelestialBody *moon;
}
@property(nonatomic, retain) NSString *name;
@property(assign) int *mass;
@property(nonatomic, retain) CelestialBody *moon;
...

@implementation Planet
@synthesize name;
@synthesize mass;
@synthesize moon;
...

You get setters and getters for each of the iVars (i.e.)

[newPlanet setName:@"Jupiter"];
[newPlanet setMass:57];
NSString *closestName = [newPlanet name];
int largestMass = [newPlanet mass];

CelestialBody *newMoon = [[CelestialBody alloc] initWithName:@"Callisto"];
[self setMoon:newMoon];
[newMoon release];

but you also get the ability to release the object using ...

// Releases the object (frees memory) and sets the object pointer to nil.
[self setMoon: nil];

There will of course be deallocs for each Class.

// Moon
-(void)dealloc {
    [name release];
    [super dealloc];
}

// Planet
-(void)dealloc {
    [name release];
    [moon release];
    [super dealloc];
}

Am I getting this right?

gary

+2  A: 

Unless your planet object is declared as a property within some other class, using the retain/copy attributes, you can't release it this way.

When you declare a property using retain/copy, the resulting setter will release the old value and assign the new value, retaining or copying it in the process. If you pass nil, you will release the old value and assign nil, retaining or copying it, and retaining/copying nil is nil, so effectively you end up releasing the old value and assigning nil to the ivar.

This is an acceptable way to release instance variables.

In order to be able to release your newPlanet instance this way, you'd have to have declared it in a class as a property with either retain or copy.

As a further example, since your planet object declares its properties in this way, you could release those using this method.

Or in the Planet class's dealloc method, you could do:

self.name = nil;

This would release name and assign nil to it.

Jasarien
Thats what I was getting at, I will refactor the question to better suit what I should have written in the first place.
fuzzygoat
A: 

Your example shows the synthesis of one class's ivars (those of Planet) but the use of another (whatever "self" is). Is the "newPlanet" property of "self" in your last example also synthesized as (retain)? If so, then: Yes, setting newPlanet to nil will release whatever self's old "newPlanet" was.

Joshua Nozzi
A: 

I think you are not getting it right. After your question update, yes, you can do that, and also:

self.moon = [[CelestialBody alloc] initWithName:@"Callisto"];

and release it later, probably in your dealloc method:

self.moon = nil;

Apple Objective-c 2.0 Properties and Memory Management docs are pretty good. Check Mac Dev Center library.

madmw
Are you sure? my @property moon also does a retain, so I would need to release the alloc, and finally release the retain?
fuzzygoat
Pretty sure. The purpose of 'retain' keyword when you declare a @property is that the automatically generated accessors manage the retain/release cycle for you. You can do it yourself releasing the ivar directly, without the accessor. There are a lot of possibilities.
madmw
+1  A: 

"you also get the ability to release the object"

Yes, as long as you didn't declare it with the assign attribute.

As you probably know, one of the reasons (although perhaps not the primary one) for using declared properties is that you can do:

self.moon = aMoon;

rather than;

[self setMoon:aMoon];

They are equivalent. That means that your deallocation can look like this:

self.moon = nil;  // Releases and sets to nil

But remember to never just do:

moon = nil; // Sets to nil, doesn't release

It's very good practice to not only release the object, but to set the variable to nil, as you do, because otherwise some other code could mistakenly try to use the pointer that is left in the variable.

Felixyz
Thank you, much appreciated.
fuzzygoat