While reading the book by Mr. Kochan (1st ed): "Programming in Objective C" , I noticed that he uses the following code (you can see it at pages 342-344) to explain that the initWithString is preferable to stringWithString because the AddressCard class would own the name variable contents. Also, I don’t get any errors making repeated calls to the setName version with the stringWithString method.
//I didn't added here the header file which has the needed declarations #import "AddressCard.h" @implementation AddressCard; -(NSString *) name{ return name; } //Recommended code: -(void) setName: (NSString *) theName{ [name release] name = [[NSString alloc] initWthString: theName]; } //Incorrect code according to Kochan: -(void) setName: (NSString *) theName{ [name release] name = [NSString stringWthString: theName]; } //I skipped the rest of class implementation @end
The problem was that I didn’t quite well understand why is better to use the stringWithString method since any local variable assigned that way would have it’s memory "owned" by NSString instead of the local class.
But the fact is that I misunderstood it. After more reading, the rules are quite crisp and easy to understand :
- all objects which are returned by an
alloc
,copy
,copyWithZone
, ornew
call have a retain count of 1. - any
retain
increases the receiving object’s retain count. - any
release
decreases the receiving object’s retain count. - the
autorelease
tells the current autorelease pool to send the receiving object therelease
message “later”. - As a general rule, any factory method that doesn’t have “new” or “copy” in the name (e.g.,
stringWithString:
) returns an object that it has autoreleased on your behalf.
In English words for newbies to Objective-C as I am:
- Any method whose name contains
copy
,alloc
,retain
, ornew
returns an object that you own. - Any method that doesn’t, returns an object that you don’t own.
- To own an object, retain it.
The incorrect part of the implementation of setName:
that I showed before is the fact that it stores an autoreleased object in an instance variable, while I mean to own the object. Either I should retain it or, in this case, copy it.
The simpler case is to use alloc
and initWithString:
, as in the correct example; the other way would be copy
.