Add new Objective C subscripting to your own objects

The new Objective C literal syntax is a huge leap forward in syntax - especially in terms of accessing arrays and dictionaries using subscripts.

NSArray *anArray = @[a,b,c];
NSDictionary *aDictionary @{ a : a1, b : b1};

// New subscripting format
anArray[0];    // => returns a
aDictionary[a] // => returns a1

Have you ever wanted to add subscripting to your own app? You just need to add some secret methods:

// To add array style subscripting:
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx; // setter
- (id)objectAtIndexedSubscript:(NSUInteger)idx;               // getter

// To add dictionary style subscripting
- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key; // setter
- (id)objectForKeyedSubscript:(id)key;                           // getter

Kinda dictionary-ey?

So, let's say you want to add a hash style keyed subscript to an object, you can use it like this:

@interface Banana : NSObject
- (id)objectForKeyedSubscript:(id)key;
- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key;
@end

@implementation Banana
NSMutableDictionary *_attributes;

-(id) init {
  self = [self init];
  if (self) {
    _attributes = [[NSMutableDictionary alloc] init];
  }
  return self
}

- (id)objectForKeyedSubscript:(id)key {
  return _attributes[key];
}

- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key {
  _attributes[key] = obj;
}
@end

Banana *banana = [[Banana alloc] init];
banana[@"colour"] = @"Yellow";
banana[@"colour"]; // returns "Yellow"

Or maybe array-ey?


Or if you want to add an indexed style (like an array):


@interface BananaBox : NSObject
- (id)objectAtIndexedSubscript:(NSUInteger)idx;
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx;
@end

@implementation AppleCart
NSMutableArray *_bananas;

-(id) init {
  self = [self init]
  if (self} {
    _bananas = [[NSMutableArray alloc] init];
  }
  return self;
}

- (id)objectAtIndexedSubscript:(NSUInteger)idx {
  return _bananas[idx];
}

- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx {
  _bananas[idx] = obj;
}
@end

BananaBox *bananaBox = [[BananaBox alloc] init];
bananaBox[0] = @"Delicious banana";
bananBox[0]; // Returns "Delicious banana"

Shameless plug - I gave a talk about the new literals at the London Ruby Users Group. Check it out here: http://skillsmatter.com/podcast/home/objective-c-for-rubyists



Subscribe via RSS

Back to all blog posts