To retain or not to retain - iphone

If I am adding an item to a dictionary like this:
[connectionHandlers setObject:projectsHandler forKey:[NSNumber numberWithInt:PROJECTS_CONNECTION_ID]];
Should I be retaining the NSNumber used for the key.
Also, when an object is added to an NSArray or NSDictionary, is it retained by the Array or Dictionary when added and released when removed?
I'm trying to get my head around Memory Management on the iPhone, and it's a doozy

You do not need to retain it. Anytime you add keys or objects to dictionaries or arrays, the array or dictionary will retain it. If you retain it as well, it will be unnecessary.

Related

Info about re-alloc of an object

I have a question... If I have for example one NSMutableArray and if I use it... with for example 100 object... if I use this code:
mutablearray=[NSMutableArray alloc]init];
and add at the array others 100 objects... the first 100 object was deallocated (so the memory is free) or I must do [mutablearray release] to free memory?
thanks
if mutablearray is retained or using through copy property then surely you need to release it. And if you are not using mutablearray as property then you will need to look into the following:
Adding an object to an NSMutableArray increases it's retain count by one, giving it a retain count of 2 (1 for the alloc/init, and one for adding to the array).
so removeAllObject will take care of increased retaincount for the array and you need not to worry. Just call:
[mutablearray removeAllObjects];
You need or remove all objects from your array. In this case you don't need new array.
Or release array, at release array releases all it's objects.
You have to use [mutablearray release] to free memory because releasing the objects doesn't release the internal structures of the array.
Also, you shouldn't release objects in the array, instead remove them from the array by using any of the remove... commands of NSArray

array of dictionaries & mem mgmt

I have an array of dictionaries, which works ok. I am trying to track down a memory access issue and want to know:
If I create autoreleased strings for the dictionary, for example one string is from:
NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error];
for (NSString *file in dirContents)
When I do
NSDictionary *dictItem = [NSDictionary dictionaryWithObjectsAndKeys:file, #"file"...
Does the resulting dictItem retain the individual strings? I have been assuming so ;-)
And then I add that dictItem to an array. I assume the addObject call on NSMutableArray will retain the dictItem for me...
What about when it comes time to free up the memory?
If I simply call removeAllObjects on the array (which crashes now), will it release all of the strings inside the dictionaries as well as the dictionaries themselves?
Hope this is somewhat understandable ;-)
thanks!
Here's a quick whistle-stop tour of memory management in Cocoa collections...
NSDictionary does not retain keys. Instead it creates a copy of the key. In other words adding an object as a key in a dictionary will not increment its retain count.
NSDictionary will retain the values for the keys that you pass it.
When you release (and eventually dealloc) the NSDictionary it is responsible for calling release on the objects it has stored (not you!)
NSArray will retain any object you add to it
NSArray will release all objects it holds a reference to when it is deallocated
Knowing the above...
dicItem will not retain your key #"file" - it will copy it
dicItem will retain your object called file
when dicItem is deallocated it will call release on its copy of #"file" and file
when you add a dicItem to your array it will be retained
when you release your array and it is deallocated all the dicItems it holds will be sent a release message
releasing your array should subsequently trigger a dealloc of your dicItem objects - provided they are referenced elsewhere (i.e. leaked)
you do not need to send your NSArray object a removeAllObjects message - the array itself will clean up after itself.
I think you are making this a little more complicated than it has to be. The only memory management you need to really worry about is within your own classes. When adding to an NSArray it does in fact retain the object, and then when you call removeAllObjects or the array is destroyed, it will release all of it's contained objects. However, this is where the concept of "owning" an object is important. When any object gets a reference to an object, it can call "retain" on it to indicate that it owns the object (this also applies to allocating a new object or using the "new" operator). That means, the object knows for sure the object will be around until it is done with it. To indicate that it is done with the object, it should always release or autorelease the object and set the reference to nil.
So bottom line, if you do not call retain, alloc, or new on an object, you should never call release. If you do call one of those functions, you should ALWAYS call release or autorelease on it. For any other object that you may send a reference to, you can assume that it will take ownership of it if it wants and if it does, it will always release it when it is done.

(iphone) nsarray, nsmutablearray retain/release

this is so basic, but quite not sure how to release array object in object-c.
I know that adding an object to array retains the object.
and removing it from an array releases the object.
When I have an array(mutable or not),
does 'releasing the array itself' also removes objects inside the array(therefore sending release to each object)?
Or should I remove the object first and release the array to reverse the operation (which is retaining array and each object in it).
Thank you
Calling release on NSArray OR NSMutableArray instances will also release it's objects,

iphone - will the retain property propagate on an array?

I have a mutable array that has been retained.
This array contain dictionaries with lots of keys. Each dictionary contains objects.
Do I have to retain the dictionaries before adding them to the mutable array or will the array itself retain everything that is added to it (because it is already retained), including the sub objects of its objects in the hierarchy?
thanks.
A Foundation container, like NSArray or NSDictionary, retains the objects it directly owns, but not subobjects owned by the objects.
For example, if NSArray*a contains NSArray*b and it in turn contains NSArray*c, a retains b and b retains c but a doesn't retain c.
That said, your are thinking from a wrong perspective. It's not correct for you to wonder such as "do I have to retain this object (say x) before passing x to another object y, because y might not retain it appropriately?" The point of retain/release is that to make sure an object retains and releases objects it owns. You trust other objects to do the same.
Then, all you have to make sure if you put an object x to an array y, is for you not to release x (if it's not autoreleased) once it becomes unnecessary to you. If y needs it, y retains it, so you don't have to care about it.
Say you have a pre-existing NSMutableArray*array. Then you would do in a method something like this:
NSMutableDictionary* dictionary=[[NSMutableDictionary alloc] init];
... do something with dictionary ...
[array addObject:dictionary];
[dictionary release];
You see, it's the array's responsibility to retain the dictionary, if that array needs it. It needs it, and so it retains it. You don't have to care about that.
The method's responsibility is to retain the dictionary if the method needs it, to release it if the method no longer needs it. So, as shown above, the method releases it once it's done with it by adding it to the array.
Again: the whole point of retain/release is to allow you to consider the life cycle of an object very locally in the code.
Whenever you call a method method:of another object a by passing an object b, you don't have to worry as you do now whether method: retains b or not, and you don't have to worry if you need to retain b before passing b to method:.
It is because every method in the Cocoa framework, and every method you write, retain the object b passed to it if the method needs it later, and don't retain b if it doesn't need it later.
Objective-C containers (such as NSMutableArray) will retain the objects added to them.
This does not, however, have anything to do with anything being "propagated" -- whether or not you call -retain on the NSMutableArray is irrelevant. The NSMutableArray will simply retain objects added to it, and if those objects are themselves some kind of container (such as a dictionary), the sub-objects will themselves already have retained anything added to them, and so forth.
ps. there isn't really a "retain property", there's an (internal) "retain count" on each object. For example, if you create an NSString and add it to 3 NSMutableArray's, each of those arrays will retain it.

Does removeObject release the object in an NSMutableArray of objects?

I was wondering when you remove an object using removeObject in an array if that removed object is handled properly. Would the object being removed be released?
The NSMutableArray will release it. If that's the last retain on it, it will be deallocated. From the documentation:
Like NSArray, instances of NSMutableArray maintain strong references to their contents. If you do not use garbage collection [Jed: the iPhone does not], when you add an object to an array, the object receives a retain message. When an object is removed from a mutable array, it receives a release message. If there are no further references to the object, this means that the object is deallocated. If your program keeps a reference to such an object, the reference will become invalid unless you send the object a retain message before it’s removed from the array.
See the NSMutableArray documentation. Their example, in fact, refers to removeObjectAtIndex::
id anObject = [[anArray objectAtIndex:0] retain];
[anArray removeObjectAtIndex:0];
[anObject someMessage];
Yes. Collections retain values they collect when the values are added to the collection, which means that the values are released when they're removed from the collection.
Yes, when the object is removed from the NSMutableArray, it is released. If its retain count is 0, it will be deallocated (or garbage collected, if you were instead running on OS X with GC enabled).
As everybody has said, the object of a NSMutableArray is released after it is removed from the array.
If you don´t want to release the object, retain it just before you call remove object method. In this case, you are responsible for it to release it later:
MyClass *objectToBeRemoved=[myArray objectAtIndex:indexPath.row];
[objectToBeRemoved retain];
[myArray removeObject:objectToBeRemoved];