I'm an experienced C/C++ programmer starting to learn Objective-C development. I'm currently looking through the UICatalog sample and came across another instance of an i开发者_如何学运维diom I've seen several places and never understood.
Code:
ButtonsViewController *buttonsViewController = [[ButtonsViewController alloc] initWithNibName:@"ButtonsViewController" bundle:nil];
[self.menuList addObject:[NSDictionary dictionaryWithObjectsAndKeys:
NSLocalizedString(@"ButtonsTitle", @""), kTitleKey,
NSLocalizedString(@"ButtonsExplain", @""), kExplainKey,
buttonsViewController, kViewControllerKey, nil]];
[buttonsViewController release];
AFAIK, this allocates and initializes a ButtonsViewController, creates an NSDictionary for the ButtonsViewController and adds the dictionary to an NSMutableArray called menuList (which is a member variable of the MainViewController where the above code lives) and then releases the buttonsViewController that it just created. Later, the MainViewController uses the dictionary entry to switch views to the buttonsViewController when necessary.
My question is: why is the buttonsViewController still valid after this code? It was allocated and released with no 'retains' between. Does adding something to an NSDictionary or NSMutableArray have an implicit 'retain'? If so, was I supposed to be able to figure that out somehow, or is it just one of those things you have to read and remember?
It is standard procedure in the Cocoa frameworks for collections to retain the objects they contain. So yes, the mutable array is retaining the view controller.
This is always the case, unless the documentation says otherwise.
So, while it's true that the object is valid afterwards because the collection retains it, I'm not sure it's useful to think of it that way. If you intend to use the object in that method after adding it to the collection, you shouldn't release it until you're done with it.
The way to think about it is this:
1) I have a claim of ownership of this object I created
2) Now the collection and I both have ownership of this object
3) Now just the collection does, and I shouldn't use the object because I don't have ownership of it
and ignore the fact that you can technically get away with not paying attention to 3 in this case.
This allows you to keep using the NARC (new-alloc-retain-copy) rule for thinking about what retains objects.
As mentioned, NSDictionary and NSArray send retain messages to objects added and also send release to objects when removed. The code above is conceptually transferring ownership of buttonsViewController to the dictionary. An example of how you might know this... from the documentation :
-addObject:forKey:
Parameters: anObject - The value for key. The object receives a retain message before being added to the dictionary. This value must not be nil.
-removeAllObjects
Discussion: Each key and corresponding value object is sent a release message.
Yes, containers like NSDictionary and NSMutableArray retain (or copy, in the case of dictionary keys) the objects you put into them.
See the Collections Programming Topics guide from Apple.
精彩评论