Is setting a retained property to nil enough? - ios

I see some code with
#property (nonatomic, readwrite, retain) id something;
And they synthesise it:
#synthesize something = something_;
And in the constructor:
self.something = #"HELLO!";
I assume that, the above line effectively retains that string.
But then, in their dealloc method, they do this:
[self setSomething:nil];
I guess that it is fine, because I imagine that when you set a property to nil, the old value is released. But then, I noticed that all the other classes they did had something like
[something release];
Instead, so I'm no longer sure. Are both ways correct?

Short answer: Use ARC. It takes care of this stuff for you. It's much less error-prone, and just as fast as manual reference counting.
Longer answer:
If you use retained properties, then yes, setting the property to nil is the correct thing to do.
like this:
self.something = nil;
That works because the setter for a retained property first releases the old value, then retains the new value and assigns it to the property's iVar. Since the new value is nil the retain does nothing.
If in your second example:
[something release];
something is the iVar for a property, this code will cause a future crash if it is called from anywhere but in the code for the object's dealloc method. The reason is that this releases the object, but does not zero out the iVar. Later, when the object that has a something property is released, its dealloc method fires. The code in the dealloc method should attempt to release the object's retained properties. Sending release to an object that was already deallocated causes a crash.
In your case, you are asking about the code in a dealloc method. In dealloc, calling [something release] and setting the property to nil have the same result of releasing the object. Invoking the setter is probably safer, though, since custom setters sometimes have other code with additional "side effects." Since you're writing the dealloc method, you should be the author of the class, and should be aware of any special code in the setter method.
Now, if something is an instance variable, not a property, the correct thing to do is
[something release]
something = nil;
EDITED 5 June 2014 to discuss the case of code in a dealloc method.

Better to use [something_ release]. This won't cause setter to be called, which otherwise could cause some actions to be performed that are undesired in dealloc.

Both are correct, [self setSomething:nil]; will be better, when something is released to 0 retainCount then dealloc. This prevent using something from crash with BAD_EXE.
As mifki said, setter to be called if use [self setSomething:nil]; so this is depended on what have you done in setter method, a good setter should care about set value to nil, and deal with the case properly, and will not be undesired.
And even if setter method implement can't be cared to set to nil always, the better release style should be :
[something_ release], something_ = nil; //this should be safely release always

Related

Can an object be deallocated during method execution?

Let's assume that we create an instance of class var foo: Foo? = Foo() on the main thread and we call some time consuming instance method bar of Foo on another thread, after a short time we set foo to nil on main thread. What happens with the execution of bar, in my understanding bar should still continue its execution since invoking instance method implicitly passes self as the first argument, so even those the last explicit ref to foo was broken we still have a ref inside of a method and it should be good. But then I found this stackoverflow post which completely breaks my understanding. So, can somebody confirm/deny the fact that object cannot be deallocated during its method execution
Short answer is that your belief is correct, and you're looking at a question that's not relevant to Swift.
Your link is to non-ARC Objective-C. Swift always uses ARC, and ARC is very conservative about retains. Consider the following Objective-C call:
[target runMethod: parameter];
Under ARC, this is (conceptually) transformed into:
[target retain];
[parameter retain];
[target runMethod: parameter];
[parameter release];
[target release];
retain and release are atomic, thread-safe calls.
A similar behavior exists in Swift. Because of this, as a general rule (in the absence of Unsafe), a variable cannot "disappear" while you'll holding onto it.
This is the implementation detail. The better way to think about it is that by default variables and parameters are strong, and an object cannot be destroyed while there is a strong reference. This matches your understanding.
Prior to ARC, though, you needed to insert extra retains and releases yourself to protect against this kind of situation, and it was very common not to. (Prior to 10.6, most ObjC was single-threaded.)
Even without threads, there are ways this can go astray without ARC. Since callers often didn't immediately retain returned values if they only needed them temporarily, it was possible to get dangling pointers even without multiple threads. For example, with a trivial accessor with no memory management, this can crash:
NSString *name = [person name];
[person release];
[self doSomethingWithName: name];
This is why you often see old ObjC getters written in the form:
- (NSString*) title {
return [[title retain] autorelease];
}
This made sure that the returned value would survive until the end of the event loop even if self released it or self was deallocated.
Swift does similar things via ARC, but as the name suggests, it's all automatic.

Using self and self properties inside a block in non-arc environment

I have been using blocks and familiar with the memory management when using self inside blocks in
Non-ARC environment
But I have two specific questions:
1) I understand I can use __block to avoid the retain cycle a retained block which in turn using self can create, like below:
__block MyClass *blockSelf = self;
self.myBlock = ^{
blockSelf.someProperty = abc;
[blockSelf someMethod];
};
This will avoid the retain cycle for sure but I by doing this I have created a scope for self to be released and eventually deallocated by someone else. So when this happen self is gone and blockSelf is pointing to a garbage value. There can be conditions when the block is executed after the self is deallocated, then the block will crash as it is trying to use deallocated instance. How do we can avoid this condition? How do I check if blockSelf is valid when block executes or stop block from executing when self is deallocated.
2) On the similar lines suppose I use block like below:
__block MyClass *blockSelf = self;
self.myBlock = ^{
[blockSelf someMethod:blockSelf.someProperty];
};
// I am taking someProperty in an method argument
-(void) someMethod:(datatype*)myClassProperty
{
myClassProperty = abc;
}
Now there can be situations where self is not released but someProperty is released before someMethod's execution starts (This could happen when there are multiple threads). Even if I do self.someProperty = nil; when it is release, myClassProperty is not nil and pointing to some garbage, hence when someMethod is executed the first line will lead to crash. How do I avoid this?
This is the same issue as non-zeroing weak references everywhere else in non-ARC code, e.g. delegates etc. (MRC doesn't have zeroing weak references; so these are the only kind of weak reference in MRC. Yet people were still able to write safe code in the pre-ARC days.)
Basically, the solution is that you need a clear map of ownership. Either self is responsible for keeping the block alive; or some other object is responsible for keeping the block alive.
For example, with delegates, usually, a "parent" object is the delegate of a "child" object; in this case the "parent" object is responsible for keeping the "child" object alive, so the "parent" object will outlive the "child" object, thus the back reference can be weak and is safe (because the child object's methods could only possibly be called by the parent object while the parent object is alive).
On the other hand, if you have an asynchronous operation, and the block is given to the operation as a callback, then usually the operation is responsible for holding onto the block. In this case, self would not hold onto the block. And the block would hold a strong reference to self, so that when the operation is done, it can still safely do whatever it is that it needs to do on self. In fact, whatever object self is, it doesn't even need to be retained by whoever uses it, since it is indirectly retained by the asynchronous operation -- it can just be a create, fire, and forget kind of thing.
If you have something where the block is sometimes kept alive by self, and sometimes kept alive by something else, then you should re-think your design. You say "There can be conditions when the block is executed after the self is deallocated"; well, you should describe your whole design and how this can happen. Because usually, for something that is executed asynchronously, self need not hold onto the block.
Your code is really confusing and doesn't make sense. For example, why would you assign to a parameter (myClassProperty)? What's the point of passing an argument when the parameter is going to be overwritten anyway? Why would you name a local variable "myClassProperty"?
What I think you are asking about is accessing a property that can be changed on different threads, and how to deal with the memory management of that. (This question is unrelated to blocks or ARC/MRC. It is equally an issue in ARC.)
The answer is that you need an atomic property. You can make a synchronized property atomic, or implement an atomic property manually if you know how. What an atomic property of object pointer type needs to do is its getter needs to not just return the underlying variable, but also retain and autorelease it, and return the result of that. The retrieval and retaining in the getter occurs in a critical section that is synchronized with a critical section in the setter that includes the release of the old value and retaining of the new. Basically, this synchronization guarantees that the value will not be released in the setter in between retrieving the value and retaining it in the getter. And the value returned from the getter is retained and autoreleased, so it is guaranteed to be alive for the duration of the scope.
Solution for 2)
__block MyClass *blockSelf = self;
self.myBlock = ^{
datatype* p = [blockSelf.someProperty retain];
[blockSelf someMethod:p];
[p release];
};
// I am taking someProperty in an method argument
-(void) someMethod:(datatype*)myClassProperty
{
myClassProperty = abc;
}
For 1) don't know how you use myBlock. If it's used only by self, then all will be fine. And if it's used by some other object, then it's also should have retained reference at self and then there is also all will be fine.

What is the point of calling "#synthesize slider = _slider;"

Can someone explain to me the significance of creating (what seems to be) an extra variable and why put an underscore before a new variable with the same name as the last.
I have read that it is to do with creating instance variables but why would you want to create a UI element as an instance variable? Can you please provide a use case?
This objective c code for use in iOS development.
Thanks.
When you #synthesize a property and you do not provide your own getter and setter methods (in which case there is no need to #synthesize) then there is always a new instance variable created. By default it gets the same name as the property. So #synthesize slider; makes an instance variable named slider behind the scenes.
The problem here is that you might mistakenly type slider = xxx when you really meant to use self.slider = xxx. When you make something a property, best practice says you should always access it through self.propertyName (except in your init and dealloc methods and any custom getter and setter methods).
So in order to avoid this, the #synthesize statement is used to rename the backing ivar into something that is harder to confuse with the property. If you now use slider instead of self.slider the compiler will give an error message because slider is no longer the name of an instance variable.
The reason for doing that is to make the instance variable clearly stand out from the property dotting syntax. It also has the practical effect of avoiding shadowing of instance variables from argument names, which also occur in some situations.
The reason for using an instance variable at all is in most cases to avoid KVO triggering in dealloc. If you do this, you risk triggering KVO in such a way that your observers gets a deallocated object passed to them, causing an EXC_BAD_ACCESS.
- (void)dealloc
{
self.slider = nil;
[super dealloc];
}
So it's common to do this instead, which will not trigger KVO since you don't do property access.
- (void)dealloc
{
[_slider release];
[super dealloc];
}
This is commonly used to synthesize the property to a private prefixed or suffixed ivar. It tries to prevent you from accidentally accessing the ivar and not the property or overriding the ivar with a method argument.
Consider this:
#implementation MYClass
#synthesize flag = flag_;
- (void)doSomethingWithFlag:(BOOL)flag {
if (flag) {
// You do not need to worry about confusing the ivar
// flag and the param flag because it is synthesized to flag_
}
}
- (void)doSomething {
if (flag) { // Doesn't work -> use accessor self.flag
...
}
}
#end

When to make object nil and when to call release

Today I see code in which user is releasing the object first and then he is making that object nil. like this
[objectA release];
objectA=nil;
I have read at many books that we should make the object nil while leaving the view and release the object later(in dealloc method of course this method is called after viewWillDisappear or viewDidDisappear).
Now i want to know that which approach is better?
Setting to nil and releasing are two distinct operations.
You release an object to relinquish ownership of it. This is covered in the standard Memory Managemange Guidelines. If you are not familiar with them, you should read them before doing any further iOS programming.
After releasing an object, you should set it to nil if you know that some other code may attempt to access that variable later. This is most common with instance variables.
For example, you may use an instance variable to store some sort of cache:
- (NSArray *)items
{
if (!cachedItems) {
cachedItems = [[self calculateItems] retain];
}
return cachedItems;
}
Later on you may need to clear this cache:
- (void)invalidateCache
{
[cachedItems release];
cachedItems = nil;
}
We need to set cachedItems to nil because our items method may attempt to use it later. If we do not set it to nil, messages send to the (now released) cache can lead to a crash.
So set a variable to nil after releasing it when it can potentially be access by other methods in your class at a later point in time.
I don't think is important set object to nil, but is good to do.
If you do :
objectA = nil;
[objectA release];
You have LOST the memory, and this is a memory leak. If you only do [objectA release], you will release the memory, but the objectA still point to the memory, so if you try to do things like:
if (objectA==nil)
This will return FALSE, because objectA is NOT a nil. But because you do this almost in
- (void)dealloc;
you don't need set it to nil in this function.
If the object is created locally:
I would go with the first approach, it's a common practice to release the object first then assign an nil.
I haven'nt read about your second approach in any book.
If the object is the part of class variable and have retain and #synthesize :
The below will do the both work (first release then assign nil through setter function) at once.
self.object = nil ;
First approach is the way to go for you..
[objectA release];
objectA=nil;
Also making object nil is a good practice (not if you are using it later) because after releasing the object, if I accidentally refers to it again your app will crash. But if you gave nil to the object, and you refer to it later it won't crash in objective C.(Situations similiar gave nullpointerException in languages like java)
ie
[objectA doneSomeTask];
wont crash,even if objectA is nil. As objective C silently ignores refering to nil.
What you have read in books does not work. If you set the object to nil you can not release it later because you can not excess the object then. You should to the first approach.
Best way:
[objectA release]; // sightly sightly faster since less function calls
objectA=nil;
Lazy way:
self.objectA=nil;
it will call:
(void)setObjectA:(ObjectAClass *)objectA
{
[objectA release]; // <-- original value is released
objectA = [objectA retain];// <-- set the point to nil and do nothing since nil
}

Ambiguous scenario for iPhone memory management

I have some difficulties to understand this scenario.
I create an object
I set its retained property to something
I forget to release its property
I release the object
As I didn't release the property in the dealloc method, will the scenario result in a memory leak or will the property be released automatically?
The way Cocoa works is that memory management always looks locally balanced, within any one method*. This is kind of the point. You should be able to tell whether you have a leak or error in a method just by looking at that one method. No global program knowledge required.
It is your responsibility to release an object if you received the object from a -copy, -alloc, -retain, or -new method.
If you do this:
[obj setProp:foo];
is it your responsibility to release foo? No - see rules. If obj retains it (and you're saying you happen to know that it does), then it is the responsibility of obj to release it, in its dealloc method if not sooner.
So if you did this, it's balanced, no matter what kind of property -prop is.
id obj = [[MyObject alloc] init];
[obj setProp:foo];
[obj release];
*except for within the implementations of init, copy, dealloc, and accessor methods.
Yes, it's leak.
Retain, alloc will increase the counter by one.
Release will decrease the counter.
It will free the memory when the counter reaches zero.
Think of setter as this:
[newvalue retain];
[property release];
property = newvalue;
So..
create an object => 0+1=1
assign it to some object as a retain property => 1+1=2
release the object => 2-1=1
You will have to release that object again sometime.
And, trust me autorelease doesn't work quite well in the iphone environment.

Resources