OK, looking at this:
Apple docs: Declared Properties
If you scroll down to dealloc it reads:
"Typically in a dealloc method you should release object instance variables directly (rather than invoking a set accessor and passing nil as the parameter), as illustrated in this example:"
- (void)dealloc {
[property release];
[super dealloc];
}
"If you are using the modern runtime and synthesizing the instance variable, however, you cannot access the instance variable directly, so you must invoke the accessor method:"
- (void)dealloc {
[self setProperty:nil];
[super dealloc];
}
Now, I must own at least 15 to 20 books on iOS development. I can't say that I have ever seen any code in these books proposing that one do anything other than:
[someproperty release];
Is there a compelling reason to edit a bunch of files of code that works perfectly well to adopt Apple's recommendation? How about future work? Or, are they pretty much equivalent?
Apple's document appears to apply only if you have synthesize-by-default turned on. If you have it turned off, which seems to be the default case, you need #synthesize, which gives you access to variables directly.
Personally, I do:
#synthesize someProperty=_someProperty;
just so I can then do:
- (void)dealloc {
[_someProperty release];
[super dealloc];
}
See Jeff LaMarche's blog for more.
On the modern runtime, you no longer have to declare instance variables for properties, nor do you have to write #synthesize in the implementation. If your code already has the instance variables declared, then there's no reason to replace code that calls release with a call to a set accessor (the first quote you pasted even states that).
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Dealloc method in iOS and setting objects to nil
As to property dealloc in object c, i have seen different kinds of forms. Which of following is best/correct
//Kind1:
- (void)dealloc
{
[_property release];
[super dealloc];
}
//Kind2:
- (void)dealloc
{
self.property = nil;
[super dealloc];
}
//Kind3:
- (void)dealloc
{
[_property release]; _property = nil;
[super dealloc];
}
Your second option is inadvisable. Property setters may have side-effects and generally aren't implemented with the consideration that the object may be half torn down already. In general you should avoid any method calls to self (or super) from dealloc, other than [super dealloc]. You should also avoid non-trivial calls (i.e. anything but release) on other objects, as you may have circular references that can lead back to references to your half-deallocated object.
The first option is perfectly sufficient. Note that if you use ARC it is redundant. Using ARC is your best bet, invariably, as it's not only safer but faster.
The third option is controversial. Some people argue that it makes your program more resilient to errors (since references after dealloc may end at the zeroed instance variable, rather than bouncing through it and seg faulting, or worse). They also argue that it ensures that if you do run a method which tries to use the value, it'll probably fail gracefully (again, rather than dereferencing what is a dangling pointer at that point). But if you subscribe to my first point on avoiding this to begin with, it becomes somewhat moot. And my experience is that relying on that behaviour is a bad idea - even if it's a clean design to begin with, it's easy to forget about it and end up changing the code some time later, in a way that breaks it.
And those that dislike the third option also argue that it hides errors. Some go as far as explicitly overwriting not with nil but rather an obviously bogus value (e.g. 0x0badf00d) to make it clearer if and when a dangling pointer is dereferenced.
Kind1 is more than enough;
It is usually not a good idea to use 'self' on alloc and dealloc. coz self will call setter/getter method, and if u have custom setter/getter method its can cause trouble.
You should never call self. in dealloc.
Once you have release-ed then there is no advantage whatsoever of making it nil.
So, first one is the correct way to use dealloc.
What is the equivalent keyword i can use in the place of self in ARC enabled projects?
ex:- [self mymethod]; what is ARC equivalent of this method call?
I don't quite get it? Why ARC should have different syntax for method calls? It is an automatic memory management, where in most cases you won't need to use retain/release, nothing more. So it would look like this:
[self mymethod];
In ARC(Automatic Reference Counting),you don't need to release or retain. It has nothing to do with calling methods!
ARC - Automatic Reference Counting implements automatic memory management for Objective-C objects and blocks, freeing the programmer from the need explicitly insert retains and releases. Since this is handled at compile time, no collector process is need to continually clear memory and remove unreferenced objects.
For calling a method, you still do it this way:[self mymethod];
it's still the same
[self myMethod];
But in ARC environment, IIRC, you need to do it like this: (I don't know if this is the source of your question, but when I migrated the first time to ARC, I get compile error if I'm not doing this).
#interface myController()
- (void)myMethod; // you need to declare the method here, if you haven't declared it on the .h
#end
#implementation
- (void)viewDidLoad
{
[super viewDidLoad];
[self myMethod];
}
- (void)myMethod
{
NSLog(#"!");
}
#end
hope this help
Usually I write my dealloc to look like this:
- (void)dealloc {
[coffeeList release];
[super dealloc];
}
But today I typed (see below) and was a little puzzled why I got an error running the code through the CLANG static analyser. As I say I don't usually add self to iVars in dealloc, but was just a little curious when I spotted this as to what was going on.
- (void)dealloc {
[[self coffeeList] release];
[super dealloc];
}
gary.
I'm just guessing that clang notices [self something] release (or [self.something release]) goes against the memory management conventions. An object returned from a method not having "new", "init", or "copy" in its name should be autoreleased, so releasing it again would appear to be an over-release error.
Because that's really bad form, and goes against how you should be doing things. CSA doesn't just check for semantic errors, it also checks that you're doing things the way you should be. Where the way you should be, is the way things are done in the documentation.
Is coffeeList declared as a property (and set to retain)? Then you should probably do:
[self.coffeeList release];
Regarding over-releasing. Say I have a instance variable defined in Test.h
NSString *mystring;
In my implementation Test.m I do not initialize the variable mystring anywhere. But I release it in dealloc:
-(void)dealloc {
[mystring release];
}
Is this now over-released? I've been doing the following in dealloc to avoid any issues, however, is this really necessary?
-(void)dealloc {
if (mystring) [mystring release];
}
It seems that [nil release] shouldn't do anything, can someone verify this with class members?
There is no way to over-release something that never existed in the first place.
Instance variables are initialized to nil and, thus, [mystring release] is messaging nil which is just fine in Objective-C.
Your -dealloc methods do need to call [super dealloc] at the end, though.
First, why are you creating a variable at the class level that you're not initializing anywhere?
As this post is tagged iphone and it's IMPORTANT to manage your memory in the iphone environment it's always a good idea to release something if you've defined even if you don't assign it.
You can call release on an uninitialized variable without any problems, and be sure to [super dealloc]
I have seen sample source code around that uses different ways of releasing/dealloc'ing objects, so I was wondering which way is deemed the "best" one. A few options on -dealloc:
1) Release objects
- (void)dealloc {
[obj1 release];
[obj2 release];
[super dealloc];
}
2) Set objects to nil
- (void)dealloc {
self.obj1 = nil;
self.obj2 = nil;
[super dealloc];
}
3) De-allocate objects directly
- (void)dealloc {
[obj1 dealloc];
[obj2 dealloc];
[super dealloc];
}
Which way is the best one? Pros and cons for each?
Method 1 is the only recommended method. It's also good practice to set them to nil AFTER you've released them.
Method 2 only works for properties that manage their own object/value retaining, so it's not universally applicable. And if you implement your own setter method that performs other actions when the property changes, you may get undesired side effects by calling it in [dealloc].
Method 3 violates the reference-counting principle because it will deallocate the objects even if something else has a [retain] hold on them, so when the other objects access them next, your program will crash. You're never supposed to call [dealloc] directly -- let the runtime call it when the last owner calls [release].
If obj1 and obj2 are properties using #synthesize-d accessors, then method 1 and method 2 are equivalent. If either of those two conditions is not true then the effect is rather different. If they're not properties, then method 2 just sets the pointers to nil without doing anything that would deallocate the objects. And if they are properties but you've implemented your own setter methods, method 2 calls those methods with "nil" as the argument. Whether that's equivalent to method 1 or not depends on how you've implemented those methods. If your custom setters do anything significant when the argument is nil, method 2 would ensure that this code executed.
As Marco said, method 3 is just plain wrong. If you've seen sample code doing that then the author may not actually know what they're doing.