R – Setter for NSString, how is it working

memorynsstringobjective cxcode

This question follows on from a previous question, that has raised a further issue. What I am trying to understand is just when the pointers and object in this example are being created and what ultimately happens to them. I am still trying to get my head round this, so please excuse any false assumptions I may have made.

// MAIN
int main (int argc, const char * argv[]) {
    PlanetClass *newPlanet_01 = [[PlanetClass alloc] init];
    [newPlanet_01 setGeekName:@"StarWars"];
}

.

// CLASS
@interface PlanetClass : NSObject {
    NSString *geekName;
}

- (NSString*) geekName;
- (void) setGeekName:(NSString*)gName;
@end

.

// SETTER
- (void)setGeekName:(NSString *)gName {
    if (geekName != gName) {
        [geekName release];
        geekName = [gName copy];
    }
}

(A) … When an instance of PlanetClass "newPlanet_01" is first created is the NSString instance variable object created, or just a pointer to a possible future object? If it is just a pointer what am I releasing later in the setter as its just a pointer, not a pointer to an object?

(B) … In the above example "gName" is a pointer to the NSString object @"StarWars"?

(C) … Next is the pointer geekName different from the gName (i.e. if geekName does not already point at @"StarWars")

(D) … geekName release, what is released the first time the code is run, my understanding was that geekName is just a pointer to does not point to anything. Or does release just not release anything this first time?

(E) … Finally geekName = [gName copy]; the newly released geekName is now assigned to point to a copy of gName, what happens to the original gName?

Best Answer

  1. You're creating a pointer that is initialized to nil. If you're familiar with C or Java, then nil is basically the same thing as NULL or null -- it's effectively a pointer to nothing.
  2. Yes. @"StarWars" is called a "string literal". Think of a string literal as a "permanent" string that is stored by the program, and gName (in this case) is a pointer to the memory location of that string.
  3. Yep -- that line makes sure that the incoming gName is not the same as the object's geekName variable. Assume that check wasn't there, and gName and geekName pointed to the same string -- then the next line would release that string, which could make the next line invalid (it would be copying a released string -- very bad!).
  4. Assuming geekName is still nil, then yes, nothing is released; or rather, the release message is sent to the nil object, which does nothing with the message. (Unlike C or Java, in Objective-C, you can send messages to nil -- but all such messages are ignored, and nil is the return value from all such messages).
  5. You create a copy of gName in case gName is really an instance of an NSMutableString -- you don't want other code to mutate the string that you are treating as immutable. But what happens to the original object pointed to by gName? Well, it depends on what the caller does with it. It could be released, it could be retained, it could be passed to another object...you don't really know. In this particular case, since gName points to the string literal "StarWars", nothing happens to that object (since it's a string literal -- see above). And the pointer itself is only valid in the scope of this method, and goes away once the method returns.