I know that discussions about coding styles tend to end in disaster and endless flame wars, but that’s not what I want to reach. During the last decade I mainly saw two different coding styles for dealloc
methods in Objective-C. The first and most common one was to place dealloc
at the bottom of the file. This is also the style Apple uses in the Xcode default templates. The logic behind this seems to be that dealloc
is invoked when the end of the object approaches, so the end of the file seems to be a nice metaphor.
On the other hand a couple of people tend to put dealloc
directly below the @synthesize
directives. This has two major disadvantages in my opinion:
- The top of the file gets cluttered with boring code.
- It’s harder to find the essential parts in your class, you have to scroll down.
The huge advantage in my opinion is that you have a direct visual connection between properties and the corresponding release
message.
The other thing is niling already released variables. While I don’t think that this is necessary, especially in object context where the whole variable gets desctructed after dealloc
ends, I tend to also nil the variables. I’m used to do this for variables in function scope, so I’m just consistent with my coding style.
This is how most of my classes look like:
@implementation Bar
@synthesize foo;
- (void)dealloc
{
[foo release], foo = nil;
[super dealloc];
}
// Initializers and other methods…
I already mentioned a couple of pros and cons. What do you think about this topic? What is the coding style you use in dealloc
and why? Are there other pros and cons I forgot to mention?
I don’t want to start a flame war here. I just want to know what style you use and if you have specific reasons for this or if this doesn’t matter for you in the end.
I like to put the dealloc
implementation right below the initializers. That way, when I add a new instance variable, I remember to release
it right after I init
it.
Also, I find it really helpful to use the #pragma mark
directive to make it easier to browse the file. So I "group" the init
and dealloc
methods together under a heading called "initializers". When browsing the file, having those headings makes it much easier to find what you're looking for without being distracted by the dealloc
method.
It might be boring code, but man is it important.
Don't set your ivar to nil in dealloc if you don't have a specific reason to. It serves no purpose and at best masks programmer errors that you would do better finding out about than hiding.
My order:
- Syntheses and
@dynamic
directives (I started doing these at the top sometime in 2011; previously, they were in with accessor implementations) - Class methods (
+load
,+initialize
,+sharedFoo
, others) - Initializers
dealloc
finalize
- Custom accessor implementations
- Protocol conformance methods, grouped by protocol (usually with
#pragma mark
directives) - Notification handler methods (usually declared in a class extension up at the top)
- Other methods (usually declared in a class extension up at the top)
Within the dealloc
method:
- Don't use accessor messages, implicit (property accesses) or explicit. Any impure custom accessor may not be safe to call on a partially-deallocated object. (The same goes for initializers.)
- Don't set ivars to
nil
. The object is partially deallocated; why are you still sending it messages? (If you aren't, then nothing is looking at the values of the ivars.) - (If it were somehow appropriate to set ivars to
nil
) Don't abuse the comma operator. An expression like[foo release], foo = nil
mixes the types (firstvoid
from the message expression, thenid
from the assignment expression). These are separate statements; write them as such. -
[super dealloc]
is always last and always has an empty line above it, emphasizing its presence.
Of course, I also have “Treat Warnings as Errors” turned on, so if I forget [super dealloc]
, I break my build.
I put my dealloc at the top, just under the @synthesize directives. It is a little clunky, and boring code, but oh-so-important code, so it gets top billing. Also, being able to compare between the properties and the -releases is vital.
I put it at the bottom. This allows me to simply hit end and go to it when I add something that needs deallocating. I also don't want it around my property synthesizers, because this is deceptive. Not everything I dealloc necessarily has a synthesized accessor attached to it. Heck, it isn't even necessarily all in the initializer. If I try to use a shortcut that way, I'm likely to mess it up.
- (id)init{
self = [super init];
if( self ) {
someVar = [[NSMutableArray alloc] init];
// something like the following shouldn't be released:
someString = [NSString stringWithFormat:@"ANumber: %d",10];
}
return self;
- (void)dealloc{
[someVar release]; someVar = nil;
[super dealloc];
}
that's the way i do it :)
精彩评论