RE: NSDictionary trouble
RE: NSDictionary trouble
- Subject: RE: NSDictionary trouble
- From: Jeff Laing <email@hidden>
- Date: Wed, 20 Jan 2010 04:47:47 +0000
- Acceptlanguage: en-US
- Thread-topic: NSDictionary trouble
> >> Yes, and it autoreleases it too. :-o That means it'll conveniently be
> >> released later on, which is exactly what you're running into. If you
> >> want to keep a reference to the dictionary, you should call alloc and
> >> init yourself.
I wrote:
> > No, you should just *retain* the result of dictionaryWithCapacity.
mmalc wrote:
> No, you shouldn't.
With all due respect, why not? Apple gives us all those convenience methods but you say we shouldn't use them?
(Note, my first kneejerk response was of course because I'm sure you'll find Apple docs that say explicitly "if you want to keep a reference to <x>, you should retain it" whereas it's unlikely you'll find anything that says "if you want to keep a reference to <x>, you're probably using the wrong design pattern")
(Oh, and, dictionaryWithCapacity: is really not one I'd get in a fuss about. But some of the other dictionaryWithObjects: convenience methods are too damned handy to lose. I just don't think that "best practice" should be something that changes depending on which particular convenience method you are talking about)
> If you're writing an init method and want to assign the dictionary to
> an instance variable, you should use alloc/init.
>
> If you want to assign the dictionary to an instance variable, you
> should use an accessor method. In this case, it's still better to use
> alloc/init then release the dictionary when you've finished with it.
That's seems a really aberrant case, where you are creating an empty dictionary with a nominated capacity. I can't visualize a case where you would do such a thing, outside of the initialiser.
> If you want to create the dictionary, use it temporarily, then forget
> about it, then dictionaryWithCapacity is OK, but again (particularly on
> iPhone) best practice is still to use alloc/init+release.
There are cases like the NSFileManager where you need to pass in a dictionary of options that describe the directory being created (for example) - should I really be creating temporary variables for those, or using the convenience methods (dictionaryWithObject:forKey:)?
I'm assuming you are saying 'don't use the convenience methods because the autorelease pool won't empty quickly enough'. Certainly Ken said it, though he seemed to assume that there was only one pool, that people would not be creating their own in their known trouble-spots.
Ken Thomases wrote:
> The autorelease pool is convenient and in some cases necessary, but it
> does come at some cost. It has some overhead in terms of time and
> memory, plus it tends to increase the peak memory usage of your
> program. (Over time, assuming you've got all your memory management
> correct, a program's memory usage will come out the same, but
> autoreleased objects accumulate over the lifetime of the current pool,
> causing spiky memory usage.)
But implicit in that seems to be that -[NSDictionary initWithObjectsAndKeys:] won't add to the auto-release pool and I don't see where that's a valid assumption (or at least a documented assumption). If you look at some of the stack traces in Instruments, you find things being created way down in the bowels of the frameworks that you wouldn't necessarily expect. (Date Formatter, I'm looking at you)
I'm increasingly of the opinion that to be properly paranoid (that is, to not assume anything about the behavior of 3rd party (including Apple) classes) and survive in the limited memory world of the iPhone, you should be writing your initialisers like this:
- (id)initLikeJeffThinksYouShould
{
if (self = [super init]) {
// Assume incompetence in others and you'll never be disappointed, only pleasantly surprised.
NSAutoreleasePool *pool = [NSAutorelease pool new];
_var = [[SomeoneElsesClass someMethodWhichMightFillThePool] retain];
[pool drain];
}
return(self);
}
That's all putting aside that by calling dictionaryWithCapacity: it seems to me that the NSMutableDictionary framework has more chance of re-using one it had lying around in some cache - yes, initWithCapacity: could do that as well, but there would still be the memory-churn expense of the alloc/release that would not be needed by dictionaryWithCapacity
It might not do it today but if I give the system the clearest possible indication of what I want (and not just the steps I think it should go through), I leave more scope for clever software engineers to add extra optimizations under the covers in future revisions.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden