> >> 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 (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to