I have a question here: Confusing double free error message/memory leak in iPhone app which I think needs a new question to answer it.
The code I am interested in i
You technically only need to use properties for values that are intended to be accessible from other classes, but many find it easier to use (retained) properties for all pointer-type instance variables so that the retaining is a bit more automatic. (And then use self.propertyName = xxx;
notation for setting and self.propertyName = nil;
for releasing in dealloc
.)
Yes, you can do the retains and releases "manually", but it's a hair tedious to do so, and you tend to muck things up when you make "quick edits". The one thing you have to watch out for, though, is assigning a retained (not simply autoretained) value (such as your alloc/init
values) to a self.xxx
property. This will result in double retain, if you don't mitigate it somehow.
Another thing to do, if you don't use properties, is to always nil
a pointer value after you release
it. This prevents you from accidentally using the released value and and it prevents you from doing a double release
.
(Note that it's in no way "bad programming" to use "lazy" techniques like I described above, vs "perfectly" figuring out everything. About 98% of programming is debugging, and anything you can do to prevent bugs or make them easier to find is goodness.)
(I'll also note that your problem in the above code appears to be mainly that you do not nil
thetdest
et al pointers after releasing them. And your if
tests should likely check to see if the pointer has been nilled before using it.)
Added: Note that the above applies to pre-ARC programs. With ARC the "rules" change substantially.
Properties do a lot of things. At the most superficial level, they let you access your member variables in dotted form. At best, they can be excellent memory management tools (and more).
Let's say you have a variable:
NSNumber * myNumber;
Later in the code, you access it as:
myNumber = [NSNumber numberWithInt: 5];
The problem is that you might lose reference to the previously stored value in myNumber. Possible Memory Leak!! At this point, you don't have a retain on myNumber and it may get dealloc'd before you're done using it.
How can properties help? Let's say you defined a property around it and used synthesize:
In the interface definition:
NSNumber * myNumber;
...
@property (retain, nonatomic) NSNumber * myNumber;
and
In the implementation file:
@synthesize myNumber;
This will create a getter and setter. Meaning... everytime you assign myNumber to something as in:
self.myNumber = newNumber;
the following setter method (created by synthesize directive) gets invoked:
- (NSNumber *) setMyNumber: (NSNumber *) newNumber {
[myNumber release];
myNumber = newNumber;
[myNumber retain];
return newNumber;
}
Here, myNumber gets a retain automatically. This is very tedious to do by hand everytime... as you can see, it's much easier to use properties.
This is still not a perfect solution, though! Why? What if you use the following statement in your implementation:
myNumber = newNumber;
Remember, properties' getter and setter get invoked only if you're using the dotted notation (self.myNumber
). So here, using properties has done nothing for us, 'cause we forgot to use them!
This is very common and likely lapse and understandingly frustrating.
So, what's the best way? This is what I recommend (as do countless others):
In the interface class:
NSNumber * _myNumber;
...
@property (retain, nonatomic) NSNumber * myNumber;
In the implementation file:
@synthesize myNumber = _myNumber;
Now, you can access your-number as:
self.myNumber = whateverNewNumber;
But, if you did:
myNumber = whateverNewNumber;
You'll get an error... because myNumber variable just doesn't exist... forcing you to use self.myNumber
everytime!
Also, if you do choose to go this route, don't forget the dealloc:
- (void) dealloc {
[_myNumber release];
_myNumber = nil;
}
or more succinct:
- (void) dealloc {
self.myNumber = nil;
}