Object c property dealloc, which one is correct? [duplicate] - iphone

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.

Related

Can we check if the object is nil or not, before going to release in dealloc method of a class

Can we check the object is nil or not before going to release in dealloc method. I am new to objective C. Is this right way to avoid segmentation issues?.
-(void)dealloc{
if(stringObject!=nil){
[stringObject release];
}
}
Testing for nil before release is fully redundant in Objective C and will not add any resiliency to your code.
Indeed, the whole point of segmentation faults (EXC_BAD_ACCESS) is having a pointer which is not nil, thus points to some memory, and accessing that piece of memory after it has been freed.
If the pointer is nil in the first place you will not be possibly able to access any memory with it and you will not have a segmentation fault in Objective C (unlike C or C++).
The real solution to segmentation faults is correct memory management. If retain/release management seems too complex, you can have a look at ARC, which has its own intricacies, though (although much less than manual retain/release management).
A simple
if(stringObject)
will do, if you just want to check if the variable points to an object.
But with Objective C it is not necessary to test for nil because an message to a null object will simply do nothing. So it is enough to say:
-(void)dealloc
{
[stringObject release];
stringObject = nil;
[super dealloc]; //added because of the comments
}
Under ARC, you can leave out the whole dealloc in most situations, because 1) the release is managed automatically, and 2) the call to dealloc is the made just before the object ends it's life, so the nil is not necessary. However, if you use custom c-style allocation you may still need an alloc method. But this belongs to an advanced topic.
Here's a link to the dev guide on working with objects in general:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithObjects/WorkingwithObjects.html#//apple_ref/doc/uid/TP40011210-CH4-SW1
This suffices as a nil test (your way is also correct, just slightly longer):
if (stringObject)
{
//do something
}
But in a simple case like yours, you don't even have to do that, because in Objective-C, sending messages to nil objects just means nothing happens:
[aNilObject doSomething]; //nothing happens, this is perfectly valid and won't throw an exception; it won't even log anything. Once you're used to it, it's great and avoids lots of boilerplate nil checks.
Going further, in your case, you should switch to ARC (after you're done learning manual retain and release, which is a good exercise).
Your code would then look like this:
//you don't need to call dealloc at all in ARC :)
Yes you can. Before ARC there was a very common macro defined
#define SAFE_RELEASE(object) if (object != nil) { [object release]; object = nil; }
NOTE: However, sending a message to nil will return nil.

Does passing an object as a parameter for a method increment its retain counter under ARC? [duplicate]

When compiling with ARC, method arguments often appear to be retained at the beginning of the method and released at the end. This retain/release pair seems superfluous, and contradicts the idea that ARC "produces the code you would have written anyway". Nobody in those dark, pre-ARC days performed an extra retain/release on all method arguments just to be on the safe side, did they?
Consider:
#interface Test : NSObject
#end
#implementation Test
- (void)testARC:(NSString *)s
{
[s length]; // no extra retain/release here.
}
- (void)testARC2:(NSString *)s
{
// ARC inserts [s retain]
[s length];
[s length];
// ARC inserts [s release]
}
- (void)testARC3:(__unsafe_unretained NSString *)s
{
// no retain -- we used __unsafe_unretained
[s length];
[s length];
// no release -- we used __unsafe_unretained
}
#end
When compiled with Xcode 4.3.2 in release mode, the assembly (such that I'm able to understand it) contained calls to objc_retain and objc_release at the start and end of the second method. What's going on?
This is not a huge problem, but this extra retain/release traffic does show up when using Instruments to profile performance-sensitive code. It seems you can decorate method arguments with __unsafe_unretained to avoid this extra retain/release, as I've done in the third example, but doing so feels quite disgusting.
See this reply from the Objc-language mailing list:
When the compiler doesn't know anything about the
memory management behavior of a function or method (and this happens a
lot), then the compiler must assume:
1) That the function or method might completely rearrange or replace
the entire object graph of the application (it probably won't, but it
could). 2) That the caller might be manual reference counted code, and
therefore the lifetime of passed in parameters is not realistically
knowable.
Given #1 and #2; and given that ARC must never allow an object to be
prematurely deallocated, then these two assumptions force the compiler
to retain passed in objects more often than not.
I think that the main problem is that your method’s body might lead to the arguments being released, so that ARC has to act defensively and retain them:
- (void) processItems
{
[self setItems:[NSArray arrayWithObject:[NSNumber numberWithInt:0]]];
[self doSomethingSillyWith:[items lastObject]];
}
- (void) doSomethingSillyWith: (id) foo
{
[self setItems:nil];
NSLog(#"%#", foo); // if ARC did not retain foo, you could be in trouble
}
That might also be the reason that you don’t see the extra retain when there’s just a single call in your method.
Passing as a parameter does not, in general, increase the retain count. However, if you're passing it to something like NSThread, it is specifically documented that it will retain the parameter for the new thread.
So without an example of how you're intending to start this new thread, I can't give a definitive answer. In general, though, you should be fine.
Even the answer of soul is correct, it is a bit deeper than it should be:
It is retained, because the passed reference is assigned to a strong variable, the parameter variable. This and only this is the reason for the retain/release pair. (Set the parameter var to __weak and what happens?)
One could optimize it away? It would be like optimizing every retain/release pairs on local variables away, because parameters are local variables. This can be done, if the compiler understands the hole code inside the method including all messages sent and functions calls. This can be applied that rarely that clang even does not try to do it. (Imagine that the arg points to a person (only) belonging to a group and the group is dealloc'd: the person would be dealloc'd, too.)
And yes, not to retain args in MRC was a kind of dangerous, but typically developers know their code that good, that they optimized the retain/release away without thinking about it.
It will not increment behind the scenes. Under ARC if the object is Strong it will simply remain alive until there are no more strong pointers to it. But this really has nothing to do with the object being passed as a parameter or not.

difference between assigning between self. and assigning from ivar directly [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
When to use self on class properties?
Difference between self.ivar and ivar?
I know that when you do
self.array = [[NSMutableArray alloc] init];
this means that I am calling the setter method.
However, I can also do:
array = [[NSMutableArray alloc] init];
Which is assigning the ivar directly, no setters is called (I assume).
Sometimes both cases will have the same effect, sometimes not.
So what is the crucial main difference between doing one over the other?
Can someone explain this clearly..
If array property is retained then 1st one will cause a memory leak. In that case you are gaining ownership twice in one line, one via alloc and one via retained property. So one release is not enough.
And in 2nd one if you release immediately after alloc then you loose the ownership immediately as you have not retained array in that case.
The crucial difference is that the setter can have additional side effects — such as retaining the argument or issuing KVO notifications — while a simple assignment can't.
The Objective-C Programming Language tells you to use direct access in the initializer:
There are several constraints and conventions that apply to
initializer methods that do not apply to other methods:
If you set the value of an instance variable, you typically do so
using direct assignment rather than using an accessor method. Direct
assignment avoids the possibility of triggering unwanted side effects
in the accessors.
and in dealloc:
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];
}
to avoid, as Chuck said, side effects like KVO notifications.
Example: in my code I have a variable that triggers the preloading of related data in advance. Sometimes I release it or set it to nil to get rid of the variable, which means I don't need to preload anything, so I use direct access. This example is rarely the case, but it doesn't cost you anything to follow this convention.

Order of release and dealloc messages

What is the recommended way of doing this. Should I call super dealloc first or last or doesn't it matter?
- (void)dealloc
{
[super dealloc];
[orderNumber release];
[orderDate release];
}
Also when it comes to overriding methods like didViewLoad - should I call super first or last?
Always call [super dealloc] last or you might easily come into trouble because you're working on a stale object.
With didViewLoad you normally call it before your own code as you want the standard initialization stuff executed before. I've seen examples in Apple's code that don't call the super implementation at all, though, so maybe there's not much going on anyway.
In this case call the super after you have released all your properties/iVars. For viewDidLoad/willAppear/etc. I usually call the super first. The order matters when your custom class is relying on an object that is created by the super. For the default viewDidLoad this is not the case so it is preference(I believe).
There is no general rule - you chose to override the method, what does it do? Do you want it to happen before or after your custom implementation?
didViewLoad doesn't appear to be a real method.
We know that [super dealloc] destroys the current object completely, so any code that comes after it is wrong. So, in this case, call [super dealloc] last.
The pointers orderNumber and orderDate are held inside your object.
[super dealloc] deallocates your object (aka self).
Once you deallocate your object you must not rely on the things inside it (e.g. orderNumber) having the values they did before you deallocated it.
Therefore, deallocate the members before deallocating the self object.
The opposite holds true for init functions - you can't initialise the pointers until after your object is constructed, so [super init] comes before you initialise the members.
Regarding viewDidLoad (et al), you do whatever works. If you have stuff you want to happen before the superclass does its thing, then you do it before you call the superclass method, and likewise for stuff you want to happen afterwards.
If you don't know whether your code should run before or after, then it probably doesn't matter.

iPhone - dealloc - Release vs. nil

Wondering if someone with experience could possibly explain this a bit more. I have seen examples of...
[view release];
view = nil;
....inside the (void) dealloc.
What is the difference and is one better then the other?
What is the best way?
When doing retainCount testing I have personally seen nil drop a count from 3 to 0 for me, but release only drops it from 3 to 2.
What you have seen is probably these:
1) [foo release];
2) self.bar = nil;
3) baz = nil;
Is releasing the object, accessing it through the instance variable foo. The instance variable will become a dangling pointer. This is the preferred method in dealloc.
Is assigning nil to a property bar on self, that will in practice release whatever the property is currently retaining. Do this if you have a custom setter for the property, that is supposed to cleanup more than just the instance variable backing the property.
Will overwrite the pointer baz referencing the object with nil, but not release the object. The result is a memory leak. Never do this.
If you are not using properties (where self.property = nil will also release an object) then you should ALWAYS follow a release by code that sets the reference to nil, as you outlined:
[view release]; view = nil;
The reason is that it avoids he possibility that a reference can be used that is invalid. It's rare and hard to have happen, but it can occur.
This is even more important in viewDidUnload, if you are freeing IBOutlets - that's a more realistic scenario where a reference might go bad because of memory warnings unloading a view, and then some other code in the view trying to make use of a reference before the view is reloaded.
Basically it's just good practice and it will save you a crash at some point if you make it a habit to do this.
#bbullis22 you have seen the restain count drop from 3 to 0 because you set the reference to nil. then you asked for the retaincount of 'nil' which is zero. however, the object that used to be referenced has the same retain count - 1 (due to setting the reference to nil).
using release, the reference still references the same object, so that's why you see the retain count drop from 3 to 2 in this situation.
As far as usage inside your code, in your dealloc you don't need the assignment to the property, releasing is all you need to do.
- (void)dealloc {
[myProperty release]; // don't need to assign since you won't have the object soon anyway
[super dealloc];
}
I think using both is kind of safety net. With only release in place you could run in problem if you screwed reference counting management. You would release an object, giving its memory back to system but pointer would be still valid.
With nil you are guaranteed that program will not crash since sending message to nil does nothing.