views:

7589

answers:

2

When adding items to NSMutableDictionary using the setValue:forKey: method (I suppose this generalizes to any NSObject) does the dictionary retain the second parameter, the NSString?

For example:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
NSString *theString = @"hello";
int i;
for (i=0; i<[theString length]; i++){
    NSNumber *myInt = [NSNumber numberWithInt:i];
    NSString *character = [NSString stringWithFormat:@"%C",[theString characterAtIndex:i]];
    [dict setValue: myInt forKey:character];
}
[dict release];
[pool release];

Clearly, there is no reason to release myInt in the loop, it is retained by dict so it can't be released until the end of the code. But is the same true of character? My thinking is that if NSMutableDictionary stores the string in some other way, then one could create a temporary pool around the loop and release those strings instead of waiting until the release of the dictionary.

I am also curious as to why retainCount of character is 7fffffff as if it is an NSConstantString, I would expect stringWithFormat to return an NSString object which would need retaining, but that doesn't seem to be the case.

+3  A: 

You don't need to retain character there, the dictionary retains it when you set it as a key and your own code has no need to retain it.

You also don't need to worry about why the retain count isn't what you expect. Maybe the Foundation framework has Flyweight-like instances of a load of single-character NSString instances. In any case if you've got the memory management correct following the guidelines, you'll be OK regardless of what the framework's doing behind the scenes. http://iamleeg.blogspot.com/2008/12/cocoa-memory-management.html

Graham Lee
+4  A: 

It's very common in Cocoa for NSString parameters to be copied instead of retained. That's because you could have just as easily given the dictionary an instance of NSMutableString. Because the string's value could change, NSDictionary makes a copy.

But, regardless of how NSMutableDictionary really operates, you don't have to worry whether character needs to be retained. Once you've passed it to NSMutableDictionary as a parameter, it's really that class's problem to decide how to store the data, unless the documentation specifically tells you that retaining the objects are your responsibility.

I also wouldn't worry too much about the retainCount of any object. Following the retain count of an object too closely can lead you down rabbit holes that just make you spin your wheels.

Finally, I really don't think you need to create your own autorelease pool here. Unless you know with absolute certainty that theString is going to be very long, or you've already observed high memory utilization in Instruments, adding the autorelease pool is an unnecessary optimization.

Alex