4
\$\begingroup\$

Sometimes I need an NSDictionary-like object that maps a few integers (non-negative) to objects. At first glance, NSMutableArray is great for this, provided that the indexes aren't too high so I came up with a quick category to allow holes in an array:

@implementation NSArray (FoundationAdditions)

-(id) objectAtCheckedIndex:(NSUInteger) index {
    if(index >= self.count) {
        return nil;
    } else {
        id result =  [self objectAtIndex:index];
        return result == [NSNull null] ? nil : result;
    }
}

@end


@implementation NSMutableArray (FoundationAdditions)

-(void) setObject:(id) object atCheckedIndex:(NSUInteger) index {
    NSNull* null = [NSNull null];
    if (!object) {
        object = null;
    }

    NSUInteger count = self.count;
    if (index < count) {
        [self replaceObjectAtIndex:index withObject:object];
    } else {
        if (index > count) {
            NSUInteger delta = index - count;
            for (NSUInteger i=0; i<delta;i++) {
                [self addObject:null];
            }
        }
        [self addObject:object];
    }
}

@end

Is there a better/easier/simpler way to do this? Preferably using something that's pre-existing in the Cocoa stack. Yes I know STL has some pretty good containers in this area, but mixing-in C++ just for this is overkill.

\$\endgroup\$
  • \$\begingroup\$ Can you clarify what your motivation is? Are you wanting to optimize for lookup speed, at the expense of memory usage? Something else? \$\endgroup\$ – Nate Apr 22 '13 at 4:59
  • \$\begingroup\$ @nate Both lookup speed and saving some memory – without needing to store NSNumber objects as keys if I use NSDictionary for this use. \$\endgroup\$ – adib Apr 22 '13 at 5:10
4
\$\begingroup\$

I would write a custom class that uses an NSMutableDictionary internally, boxing the indexes into NSNumber keys.

Depending on your particular use case it’s probably going to be both faster and more memory efficient than stuffing the unused array items with NSNull. Boxing the integer indexes into NSNumber key objects sounds like a lot of work performance-wise, but since the implementation uses tagged pointers, it should be pretty fast.

For extra points you can implement the object subscripting accessors (objectAtIndexedSubscript: and setObject:atIndexedSubscript:) and enjoy simple access syntax (foo[x]).

\$\endgroup\$
  • \$\begingroup\$ Yep, you're right. I started this back in iOS 3 and tagged pointers just made this obsolete. \$\endgroup\$ – adib Apr 24 '13 at 13:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.