views:

276

answers:

4

Can anyone tell me if the NSString instance variable "planetName" needs to be allocated / released by me (as in the example below) or is that done when the class instance is created / allocated?

My understanding is that int and float don't need to be, but not sure about NSString & NSArray ...

@interface PlanetClass : NSObject {
        NSString *planetName;
}
- (NSString *)planetName;
- (void)setPlanetName:(NSString *)value;
@end

Like this ...

- (id) init {
        [super init];
        planetName = [[NSString alloc] init];
return self;
}

- (void) dealloc {
        [planetName release];
        [super dealloc];
}

** ---------------------------------- ** EDIT: EDIT: Here is another version ** ---------------------------------- **

int main(int argc, const char *argv[]) {

        // ** Allocated here
        PlanetClass *newPlanet_01 = [[PlanetClass alloc] init];
        NSString *newPlanetName = [NSString alloc] init];

        // ** Set the instance variable pointer here
        newPlanetName = @"Jupiter";
        [newPlanet_01 setPlanetName:newPlanetName];

        // ** Released here
        [newPlanet_01 release];
        return 0;
}

the init & dealloc methods would then be like this ...

- (id) init {
        [super init];
        return self;
}

- (void) dealloc {
        // Always release the current copy of planetName 
        // pointed to by the class instance.
        [planetName release]
        [super dealloc];
}

The setPlanetName method would look like this ...

- (void)setPlanetName:(NSString *)newPlanetName {
        if (planetName != newPlanetName) {
               [planetName release];
               planetName = [newPlanetName copy];
        }
}

PS: I am not using properties or synthesize, I have not gotten that far yet.

cheers -gary-

+3  A: 

Your code is valid, but there's probably no reason to initialize planetName to an empty string. One of the nice features of Objective-C is that you can send messages to a nil object with no consequence. If your class is initialized and you never call -setPlanetName:, planetName will be nil (instance variables are always initialized to nil), so when your -dealloc method calls [planetName release], nothing will happen.

In general, the best practice is to use -copy when setting an NSString instance variable, and -retain when setting most other objects as instance variables. As such, your -setPlanetName: method would look something like this:

- (void)setPlanetName:(NSString *)newPlanetName {
  NSString *tempPlanetName = [newPlanetName copy];
  [planetName release];
  planetName = tempPlanetName;
}
pix0r
Not all objects are initialised to nil, only instance variables. Object pointers created on the stack remain uninitialised.
dreamlax
You should concider to make planetName a @property(nonatomic,copy).
PeyloW
A: 

Your code looks good. NSObject subclasses (NSString included) need to have their memory mananged by the object that owns them. In this case, that owner is PlanetClass.

fbrereto
+1  A: 

planetName is a pointer which, like an int or float, does not need to be allocated or initialized.

Just like you can assign values to an int or float, you can point planetName at different instances of a string, or it can point at nothing.

When you init your class, planetName will be nil (not pointing at anything). If you point planetName to an instance of a string, you have to retain that string, and release in dealloc.

In other words, this:

planetName = [[NSString alloc] init];

is unnecessary and meaningless.

In your setPlanetName method you would need to release the existing string that planetName is pointing to, assign planetName to the new string, and then retain the new string.

Your dealloc method is correct.

Darren
+1  A: 

You still have an issue with your new code.

In your main function, you release newPlanetName but this is a little wrong. Your PlanetClass retained it with its setPlanetName: method, but your PlanetClass never releases it again unless the name of the planet changes. It should not be up to the caller of setPlanetName: to keep hold of the string, it is your classes responsibility to deal with it appropriately.

Your old dealloc method is correct. It should release the planet's name because your PlanetClass no longer needs it. Your main method should not release the planet's name because the string returned by stringWithString: does not belong to you, and you give it to PlanetClass to take care of.

So, keep your old dealloc method, and remove the [newPlanetName release] from the main function and you should be alright from there.

As a shortcut, you can even call [newPlanet_01 setPlanetName:@"Jupiter"] and do away with the newPlanetName variable altogether in your main function.

dreamlax
I can see why I would need to add a [planetName release] to the dealloc method. So that when the class is deallocated the current copied version of newPlanet gets released.I am a little confused about the newPlanetName as I am allocating the memory, then assigning @"Jupiter" I was under the impression that newPlanet would need to be released (code above modified)
fuzzygoat
It's a common misunderstanding. Your `newPlanetName` variable in the main function is a *pointer to an object*. When you use `[[NSString alloc] init]`, all that does is allocate and initialize an empty string, which your `newPlanetName` variable points to. When you assign it a value like `@"Jupiter"`, you changing where `newPlanetName` points to, and in fact the original object that it pointed to (the empty string) is now no longer reachable.
dreamlax
This is what I was thinking ... (*) newPlanetName is a pointer to a string object, initially it points to nil. (*) newPlanetName = @"Jupiter" sets that pointer to point to a string literal, I don't think you need to release string literals, so thats good. **BUT**
fuzzygoat
IF newPlanetName = someOtherStringObject then its pointing to an actual object, should I then be releasing newPlanetName, or is that the job of the owner of someOtherStringObject, which might be me, so I would instead need to do a [someOtherStringObject release]?
fuzzygoat
You're definitely heading in the right direction. You're right about not needing to release literal strings, but in regards to releasing other objects, it's all about how you obtain them. If the method contains the word "new", "alloc", or "copy", then you are responsible for releasing it. There are some other instances where you need to explicitly release, but you should check out the Cocoa Memory Management docs for more information.
dreamlax
I was aware of the "new", "alloc" and "copy" which is one reason why I was getting confused. In the example int main(int (modified above) I got rid of the release in main, is that now right?
fuzzygoat