If I define a NSString with retain, then call alloc on it, do I need to release twice? And how necessary is the self. in front of public variables?
Basic question here.
Say in my .h, I define a NSString:
@interface MyGreatClass
@property (nonatomic, retain) NSString *myAwesomeString;
@end
And then in my .m, I have the following code:
@implementation 开发者_JAVA百科MyGreatClass
@synthesize myAwesomeString
-(void)dealloc{
[myAwesomeString release];
}
-(void)viewDidLoad{
self.myAwesomeString = [[NSString alloc] initWithString:@"Yay"];
}
@end
Did I leak? I know, I know, whenever you call
retain
oralloc
on a method, it increases the counter in memory by one and you need to have a release statement for eachretain
andalloc
, so I suspect I do, but I am just making sure because if this is true, I have to do this for a crapload of variables in my app. Also if you do have to call release twice, where do I call the second release? Can I call both of them indealloc
, one right after the other?How nesesarry is the
self.
in front of variables when referring to properties of the class you are in? What happens if you don't have it and when exactly is it necesarry?
Yes, that will leak because it's overretained. The four standard correct solutions are:
// Solution 1:
NSString *stringToBeAwesome = [[NSString alloc] initWithString:@"Yay"];
self.myAwesomeString = stringToBeAwesome;
[stringToBeAwesome release];
//Solution 2:
self.myAwesomeString = [[[NSString alloc] initWithString:@"Yay"] autorelease];
// Solution 3:
self.myAwesomeString = [NSString stringWithString:@"Yay"];
// Solution 4:
myAwesomeString = [[NSString alloc] initWithString:@"Yay"];
You'll notice the last one doesn't start with self.
, which brings us to your second question. If you don't write self.
, you are not accessing a property. That myAwesomeStirng
in Solution 4 is an instance variable, accessed directly. It won't go through the property accessors, so it won't retain the value you assign and it won't release any value that the variable held before.
Yes. Because it's
@property (retain)
, when you setself.myAwesomeString = ...;
it will be retained automatically. Thus, you must balance your ownalloc
.But keep in mind:
[[NSString alloc] initWithString:@"Yay"]
is quite redundant. First of all, to take care of thealloc
/release
issue, you could use[NSString stringWithString:@"Yay"]
which returns an autoreleased string. Furthermore, usingstringWithString:
is mostly useless unless you have a mutable string, and can be completely done away with by using@property (copy)
instead of@property (retain)
.If you're just using a constant string, you could do
self.myAwesomeString = @"Yay";
When you use the
self.myAwesomeString = ...;
syntax, you're going through the setter method (it's as if you called[self setMyAwesomeString:...];
). And when you have@property (retain)
, this will retain the string (and release the previous value). If you just set the instance variable directly bymyAwesomeString = ...;
, you have to retain it yourself.Another advantage of this dot-syntax is that instead of having to call
[myAwesomeString release];
explicitly later (usually in your-dealloc
method), you can just callself.myAwesomeString = nil;
.
I also recommend taking a look at ARC, which will become very common in the near future, and will take care of almost all of these issues for you.
I know, I know, whenever you call release or alloc on a method, it increases the counter in memory by one and you need to have a release statement for each release and alloc ..snip..
The retain count does not increase by one when you release an object. You allocate an object using alloc, copy, or new. You increase the retain count by using retain (or copy, in cases where the value is immutable, as a NSString is). You decrease the retain count using release.
How nesesarry is the self.
Self isn't necessary, but it's recommended, since you get some memory management for free. If you declare a property as (nonatomic, retain), the runtime makes sure that the object that is currently assigned to the underlying ivar is released before the new value is assigned, and that the new value is retained as it's assigned to the ivar.
You should always release your references when you're done with them. This is the simplest way to make sure you don't leak anything. If you adhere by this practice, you should never run into a scenario where you have to double release anything.
精彩评论