Assigning nil to a variable of an initialized object is releasing it? - objective-c

I have similar question to this: What is the difference between setting object = nil and [object release] VS [object release] and object = nil?
NSMutableArray *myExampleArray = [[NSMutableArray alloc] init];
myExampleArray = nil;
I use iOS 5.0 automatic reference counting, so in fact I don't release any objects. So if I assign it to nil is it equal to [myExampleArray release] ?
I know that i can't later use myExampleArray without re-initial it. So next question. What is the best way to clear this NSArray?

Yes, in an ARC environment you never call release. So assigning nil to the variable will release the object.
In a non ARC environment, you would do a release on your own, so the object gets destroyed. But the variable would still point to the old object adress. But there is no object anymore, so you would probably get a crash (EXC_BAD_ACCESS), if you use the variable later. If you also assign nil to it, that won't happen. Because the variable won't point to the old object address anymore.
Your other question:
If you need the array later again, you can call removeAllobjects on a NSMutableArray to remove all added objects, like Ankit Gupta said already. This will result in an empty array, that is still alive, so you can reuse it.

Don't use Nil for your object
try this line:
[myExampleArray removeAllobjects];

Related

retain release common practice in iOS setter methods

The common practice in IOS setters is the following:
- (void)setMyString:(NSString *)newString {
if ( newString != myString ) {
[myString release];
myString = [newString retain];
}
}
On the contrary this is not good practice
- (void)setMyString:(NSString *)newString {
if ( myString != nil ) [myString release];
myString = [newString retain];
}
}
What is the reason checking for equality in the first case? What is the problem in the seconds case?
If you set something like this [object setMyString:[object myString]]; without checking for equality - it will be crash! Because it will be released before you send it message retain. (in case when only object own string). Also in first example we checking for equality to avoid extra operations.
I know this is somewhat redundant, but...
If the new and old object are the same then you send release to the old object and it gets deallocated, the pointer to the new object will become a dangling pointer as the object it pointed to will no longer exist (since it pointed to the same object as the old object pointer). Ex. if myString and newString point to the same instance who has a retain count of one, then you subtract one, it'll equal zero. it's too late to add one now, because it'll get deallocated. However, reverse the calls to retain and release and it should be fine. If the retain count is one and you add one, it's now two, and you can safely send release. In general, I'd say before you disown an object, assert ownership of the new one first.
Also, the first type of setter would be what you would use for retain/strong style setter. If it were assign you wouldn't need to retain/release as no ownership is supposed to be asserted. NSStrings often have a copy style setter which copies the argument and uses that, which would create a copy instead of retaining. I would generally use copy for anything with a mutable subclass as you wouldn't want someone passing in a NSMutableString and mutating it behind your back. This page goes into accessors, and you'll notice that they retain the new value before releasing the old one, and explain why.
You may take this to though the memory management, https://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/.

Assign or retain in cocos2d and objective C

Here's my current situation:
I have a NSMutableArray named dictKeyArray which I assign a property with #property(nonatomic,retain)NSMutableArray *dictKeyArray
I synthesize my mutable array in the implementation file.
Later, I have a dictionary name storeDict. I assign all the keys of the dictionary to the dictKeyArray like so:
dictKeyArray = [[storeDict allKeys] mutableCopy];
Now I use this dictionary later in my implementation file. However, when it comes to releasing it, I release it once in my dealloc method. When checking with instruments, a leak shows up! Why is dictKeyArray leaking? Should I be using assign instead of retain?
I'm still not clear on what the difference is exactly...
thank you!
You have to send it an
[[[storeDict allKeys] mutableCopy] autorelease];
Just to make this clear: mutableCopy does the same as alloc meaning you are claiming ownership of the object in question. You have to decrease the retainCount by one.
By the way: You should use the accessor you wrote for it. You are just assigning it to your iVar at the moment. If you want to make your accessors work, you will have to use something like
object.dictKeyArray = ...;
in general. Or here (as mentioned by dreamlax)
self.dictKeyArray = ...;
because you are referring to an object of this specific class the code is in.
Only this way you are ensuring your object is properly retained by your accessor. Otherwise writing the accessor code doesn't make sense at all because it never gets called.
Please note: As Josh said in the comments, your code should be valid (at least from my point of view). What I suggested is a solution that is not as error-prone as yours because you adhere to the rules (could save you from headache in the near future).
You should be using self.dictKeyArray = .... Without the self. you are accessing the instance variable directly, bypassing any memory management benefits of properties, but, remember that you own the result of mutableCopy, and assigning to a property that also takes ownership will result in double-ownership, so use:
self.dictKeyArray = [[[storeDict allKeys] mutableCopy] autorelease];

Question about NSMutableArray, pointers and release

How exactly does the addObject method of NSMutableArray work? Does it create a new instance and add it into the array or does it simply add a reference to the SAME object into the array?
If the answer is it only insert a reference to the object, then it leads to my next question:
Let's say I have the following method in one of my class ('list' is a NSMutableArray), gladly, this code works the way I wanted, but i just don't seem to fully understand why:
-(void)buyItem:(Item *)anItem
{
Item * newItem = [[Item alloc]init];
newItem.name = anItem.name;
newItem.details = anItem.details;
[list addObject:newItem];
[newItem release];
}
So basically after calling [list addObject:newItem], there would now be total of two reference pointing to the same object right(newItem, and another one in the 'list' array)?
But why does releasing the newItem object here, doesn't wipe out the one in the 'list' NSMutableArray? Aren't they pointing to the same Object?
When you are adding object to NSMutableArray using method addObject: it retains added object. This is why you can release it later and use afterwards by accessing using objectAtIndex: method.
It adds a reference and then increases the objects retain count by one. What you are doing is correct and it will still exist in the array with a retain count of one.
For your reference.
What increases an object's retain count?
It's important to understand the distinction between release and dealloc. release simply decrements the "retain count", except that when the count is decremented to zero, release goes on to dealloc the object.
In general (except where documented otherwise), when you pass an object reference (ie, pointer) to an Objective-C object, and it keeps a copy of that reference beyond the duration of your call to it, it retains the object on its own behalf, and it takes the responsibility to release the object when it is itself deallocated, or when the copy of the reference is nullified or overwritten.

Objective-C memory management: if I release a string stored in an array, it only releases this reference or it releases the object in the array?

If I have this:
NSString *lastPushed = (NSString *)[tagStack objectAtIndex:[tagStack count]-1];
.//do something with the last pushed element locally
.//do more cstuff here
.//after doing all the stuff needed in the function
[lastPushed release];
where tagStack is an NSMutableArray
If I release lastPushed, since it was not copied, or inited, will it only release this reference or will it actually release the object in the mutableArray?
You didn't alloc, new, or copy or mutableCopy lastPushed, so why are you releasing it?
Since lastPushed is a pointer to the object in the array, you are releasing that. This could lead to a problem when your array thinks that it has a valid pointer to an object but you've released it and it's been dealloced.
It will release the object in the array because both lastPushed and the array point to the same object.
As always, you should follow the management rules. Do not release anything that you have not created, retained or copied.
You shouldn't be releasing lastPushed, as you didn't use alloc, copy or new. (It's that simple.)
If you want to remove it from the mutable array, you should use the appropriate method in the NSMutableArray (removeObject or removeObjectAtIndex, etc.) Otherwise, it's unclear what you're trying to do which will bite you next week/month/year, etc.

Releasing after removal from an array & reference pointers

So some where i have a leak which is related to deleting an object under certain circumstances.
Premise:
- I have an NSMutableArray of Tree objects (a Tree object knows how to draw itself).
- I have a reference pointer (Tree *selected) which basically points to whatever tree i last touched.
- Note that the *selected pointer is a weak reference.
Ok, so far so good.
Problem:
The leak arises when i delete a Tree. From the list i make sure the tree being deleted is releasing everything internally before removing it from the array (removing it from the array should automatically call release on it).
What i tried:
I noticed that my Tree *selected pointer is being assigned the touched tree via the self property:
self.selected = tree;
...and by doing this i know that it is being retained. So what i tried to do was call:
[self.selected release];
I called this right after the tree is removed from the array.
...but at which point it crashes essentially stating it was already released.
Question:
Why am i getting this error message? I removed it from the array, however my self.selected pointer still has a retained count, thus shouldn't i be releasing it?
Perhaps I should set it to nil after the removal process?
Or, perhaps I should set it to autorelease BEFORE the removal process?
Don't attempt to micromanage the retaining/releasing of your selected instance variable. If you want selected to be a weak reference, declare it with the assign attribute:
#property(nonatomic, assign) Tree *selected;
That way it will not be retained when you assign a value to it. Conceptually, it will "piggyback" on the reference that your NSMutableArray is keeping. So when you remove something from your NSMutableArray, do it a bit like this:
if (self.selected == toBeRemoved)
self.selected = nil;
[myArray removeObject:toBeRemoved];
If you didn't explicitly specify assign and your property was retaining its contents, you were most likely getting an exception because the next assignment to self.selected after removing an element caused another -release message to be sent to the old value, which had already been released by your [self.selected release] message.
What's [probably] happening is selected points to a deallocated object, not nothing.
I'd try
self.selected = nil;
instead of releasing it explicitly. That should take care of the retain count, too.
basically, i was assigning my weak references using 'self', thus internally calling retain. i removed the 'self' and now things are fine and dandy. :)
thanks!