views:

37

answers:

2

Is there any way to create a mutable dictionary with a capacity limit rather than an initial capacity?

Say you want to create a dictionary that will only ever have, at most, 100 entries.

The capacity argument for the dictionary is an initial capacity that will be simply increased if you add more elements than you want so it's not suitable.

+2  A: 

Subclass it and override addObject to check count before adding? No built-in way.

Here is a basic example... not tested, missing init etc, but this is the core. You should also override setValue:forKey: in a similar manner.

@interface MyMutableDictionary: NSMutableDictionary

- (BOOL) setObject:(id)anObject forKey:(id)aKey;

@end

@implementation MyMutableDictionary

- (BOOL) setObject:(id)anObject forKey:(id)key {
    if ([self count] < yourLimit) {
        [super setObject:anObject forKey:key];
        return YES;
    }
    return NO;
}

@end
Jaanus
Simple enough, also allows me to do other work if I need. I'll probably use this solution. Can't reason why I didn't think of it earlier...
Alexander
+1  A: 

There is no API for this, but the code to do so is fairly simple:

void AddObjectToArray(NSMutableArray *array, id obj, NSUInteger maxCount) {
    if ([array count] < maxCount)
        [array addObject: obj];
}

Note that the above code is not thread-safe, but making it thread safe is about as simple as wrapping the function's contents in a @synchronized (array) directive.

If you want an array that can be bandied about and have this limit built-in, don't subclass the NSMutableArray class cluster. NSMutableArray's contract (the "agreement" it has with calling code) says that a call to -addObject: will add that object to the array, not that it will if the array is under a limit.

Rather, an array with a maximum length behaves differently enough from the standard behaviour that it ought not to be a subclass of NSMutableArray. This may seem like a contrivance--it's an array and you can mutate it, therefore it should be treatable as an NSMutableArray. But calling code has no way to know that its modifications will fail silently on your subclass, and will probably not be designed with such failures in mind.

If the calling code is yours, you can use the helper function defined above--you know the objects might not be added and you can code appropriately. If the calling code comes from elsewhere (e.g. Cocoa or other Apple frameworks), use a normal NSMutableArray, and cull it when the calling code is done adding objects.

Jonathan Grynspan