In Cocoa, you only own an object if you create it by using alloc
, new
, copy
or retain
. Whenever you don't own an object, you have no guarantees about that object outside the local scope in which you use it. In your example, since you didn't create the new string with any of the above mentioned methods, you have no guarantee that it will be around later if you store it.
In order to take ownership of an object (i.e., that you want it to stick around so that you can use it later) that you don't already own (i.e., you didn't create it using one of the previously mentioned methods), you must send that object a retain message. For example, if you rewrite your code as shown below, you will own the string and you won't have to worry about using it later:
// option 1
NSString *path = [[NSBundle mainBundle] pathForResource:@"foo" ofType:@"txt"];
NSString *string = [[NSString alloc] initWithContentsOfFile:path encoding:NSASCIIStringEncoding error:NULL];
// option 2
NSString *path = [[NSBundle mainBundle] pathForResource:@"foo" ofType:@"txt"];
NSString *string = [NSString stringWithContentsOfFile:path encoding:NSASCIIStringEncoding error:NULL];
[string retain];
Option 1 is okay because you specifically create the string with the alloc
message. You now own the string object until you relinquish ownership at some other time. This is probably the best option for you, given your particular circumstances (i.e., you don't really want to use the convenience constructor because you want the string object to hang around to be used later).
Option 2 is okay because you specifically take ownership of the string by sending it the retain
. In your case, this probably isn't the best option because there is an alloc/init
option available already and that's usually easier to read.
When you are done with an object and you want to relinquish ownership of the object, you send that object the release
message. It's important to remember that in Cocoa, sending an object a release
message doesn't mean that you're destroying it, just that you're relinquishing ownership.
Cocoa memory management is designed around the idea of ownership of objects. Although it may be a little confusing at first, once you wrap your head around it, it makes it a lot easier to program in the environment without introducing memory errors, leaks or other bugs. The conveniences methods (like stringWithString
) are really designed to be used when you want to create an object that you're really only using for a brief period of time and within the scope of a single function or program block. If you plan to keep an object around past that scope, using the alloc/init
or new
methods to construct the object is preferred.
For more information, please read the Memory Management Programming Guide for Cocoa. It really is considered required reading for Cocoa developers. Also, it usually takes reading it, experimenting, and reading it a few more times to really grasp, especially if you have a lot of experience with other models of memory management.